Go Hello World: Write & Run Your First Program

What Does a Go Hello World Program Look Like?
A Go Hello World program requires three elements: a package main declaration (telling the compiler to build an executable), an import "fmt" statement (importing the format package for printing), and a func main() entry point containing fmt.Println("Hello World!"). Unlike Python or JavaScript, Go enforces strict formatting rules — the opening brace must be on the same line as the function declaration, or the compiler rejects the code.
Go Hello World Basics
Every developer's journey begins with printing "Hello World" to the screen. However, simply copying and pasting code without understanding the underlying mechanics defeats the purpose of learning a systems language.
In this module, we will write your first Go program, examine exactly how the compiler processes it, and explore the incredibly strict structure that makes Golang so universally reliable.
Setting up for Success
Writing Your First Program
Inside your project directory, create a new file named main.go. In Go, the entry point for executable programs is specifically tied to a package named main.
Open main.go and type out the following code precisely. Note that Go is meticulously case-sensitive.
This tiny program introduces three critical concepts that form the architecture of every Go application ever written.
Dissecting the Code
Line 1Every Go file must declare the package it belongs to. The 'main' package specifically tells the compiler to create an executable binary rather than a shared library.
Line 3Imports external code. 'fmt' stands for format. It is part of the robust Go Standard Library and contains functions for formatting text to the console.
Line 5The definitive entry point. When your compiled program runs, the execution flow exclusively starts inside this specific function.
Running the Program
To execute this code, you have two primary options provided by the Go toolchain. Open your integrated terminal in Visual Studio Code and ensure you are in the directory containing main.go.
Option 1: The 'Run' Command
For rapid development and testing, you can use the run command.
The terminal will instantly output Hello World!.
Behind the scenes, the go run command compiles the code into a temporary directory, executes that temporary binary, and then automatically deletes it. It provides the immediate feedback loop of an interpreted language like Python while keeping the underlying performance of a compiled language.
Option 2: The 'Build' Command
When you are ready to deploy your code to production, or share it with users, you must build it.
This command invokes the compiler. If there are no errors, it will operate silently, producing a single executable file in your directory. If you are on Windows, it generates my-first-go-server.exe. On macOS or Linux, it generates an executable Unix binary.
You can run this binary identically to any other program natively on your operating system without needing Go installed.
The Opinionated Formatter: gofmt
If you have worked with JavaScript or Python, you have likely spent hours debating code formatting rules with your team. Tabs or spaces? Where do the curly braces go?
Go completely eliminates this argument. The language includes an incredibly opinionated formatting tool called gofmt.
Formatting Philosophy
| Task / Feature | Go (gofmt) | JavaScript (Prettier/ESLint) |
|---|---|---|
| Configuration | Zero configuration. It is absolute. | Endless .eslintrc and prettierrc rules |
| Code Consistency | 100% uniformity across global codebase | Varies wildly per team preferences |
| Curly Brace Position | Must be on the same line | Subjective based on JSON rules |
If you drop a curly brace to the next line in your main() declaration, the Go compiler will actually throw a syntax error. Standardized formatting is integrated directly into the compiler's strict parser logic.
Whenever you press save in Visual Studio Code (if you installed the official Go extension), gofmt instantly rewrites your file to adhere to this universal standard. This ensures that every Go developer can seamlessly read an open-source Go project built by a completely different team.
Understanding Package Structure
The package main declaration is more than a naming convention — it triggers the compiler to produce a standalone executable binary. Every other package name (like package utils or package models) produces a library that can be imported by other packages, but cannot be run directly.
In larger Go projects, you will have many packages. The entry point of the application lives in package main, while all your application logic is split across named packages:
Each .go file in the same directory must declare the same package name. Files in different directories are different packages.
The fmt Package: More Than Just Print
The fmt package (short for "format") provides more than Println. Here are the three you will use most:
The most useful format verbs are %s (string), %d (integer), %f (float), %v (default format for any value), and %T (type name of the value).
Go's Strict Unused Import Rule
Unlike most languages, Go will refuse to compile if you import a package and don't use it:
This strict rule exists to keep codebases clean — unused imports are usually the result of removing code without cleaning up imports. The goimports tool (which VS Code's Go extension uses automatically) handles this for you by adding missing imports and removing unused ones on save.
Cross-Platform Compilation
One of Go's most powerful features is built-in cross-compilation. You can compile a binary for any target platform from any development machine:
No cross-compiler setup required — the Go toolchain handles it natively. This is why Go is the language of choice for distributing CLI tools and server binaries.
Further Reading
For the previous setup step, see Go installation and setup guide. For the next step after Hello World, see Go variables, types, and constants. To understand how packages work in larger projects, see Go modules and packages.
Next Steps
You have now written, executed, and compiled your fundamental entry point application. The foundation is set. In our next tutorial, we will explore the explicit strictness of Go's type-system through declaring variables, constants, and basic data types.
Common Mistakes for Go Beginners
1. Putting the opening brace on a new line
Go's automatic semicolon insertion means func main()\n{ is parsed as func main(); — a syntax error. The opening brace must always be on the same line as the statement it belongs to.
2. Unused imports
Go treats an unused import as a compile error, not a warning. If you import "fmt" and never call any of its functions, the build fails. Remove unused imports or use goimports (part of the Go tools suite) to manage them automatically.
3. Unused variables
Similarly, declaring a variable and never reading it is a compile error in Go. This strictness prevents subtle bugs where a variable is declared but the developer forgot to use it. The blank identifier _ is the escape hatch when you deliberately discard a value.
4. Forgetting go fmt
Submitting unformatted Go code is considered bad practice. Run gofmt -w . or go fmt ./... before every commit. Most editors apply this automatically on save via the official Go language server gopls.
5. Confusing go run and go build
go run main.go compiles and immediately executes — useful for scripting and iteration. go build produces a binary you can distribute or deploy. For production, always build a binary; never deploy via go run.
Frequently Asked Questions
Do I need to install anything special to run Go programs?
You only need the Go toolchain from go.dev/dl. It includes the compiler, go fmt, go test, the module system, and gopls. No separate build tool is required for most projects.
What does package main mean?
package main is the entry-point package. When the Go compiler sees package main with a func main(), it produces a standalone executable binary. Any other package name produces a library that must be imported by another package to be useful.
Why does Go use fmt.Println instead of just print?
Go does have a built-in print function, but it writes to standard error and is intended only for bootstrapping and debugging the runtime itself. fmt.Println writes to standard output, supports format verbs, and is the idiomatic choice for all user-facing output.
