Program Entry Point
How Go starts executable programs using the main package and main function, and a step-by-step guide to writing and running your first Hello World program
Every executable Go program needs a single, well‑defined place where execution begins. That place is the main package and its main function. Without them, the Go toolchain has no way to know what code to run first when you start your program. This page explains exactly what these two pieces are, why they are mandatory, and how to write the simplest possible program that puts them into practice.
The main Package and main Function
A Go program that produces an executable binary must always declare package main at the very beginning of the file that contains the entry point. The main package is not just a convention; it is a signal to the Go compiler that this package should be built into a runnable command, not a reusable library.
Inside that package, there must be exactly one function named main with no parameters and no return value.
package main
func main() {
}
This is the minimal, valid program you can write in Go. It compiles and runs without producing any output. When you execute the final binary, the runtime calls main automatically. You never call main yourself, and you cannot pass arguments to it directly — command‑line arguments are accessed later through the os.Args slice in the standard library.
Missing Entry Point:
If either the main package or the main function is missing, the go build or go run command will fail with an error. A library package — one that is imported by other code — should never use package main and never contain a main function.
Why Go Requires an Explicit Entry Point
Languages like Python or JavaScript let you execute a file from top to bottom without a special function. Go is compiled, and the compiler needs an unambiguous starting address. The main function provides that address. It also keeps the code structure uniform: every command you write, no matter how large, has a single starting point that is easy to find.
A mental model that helps beginners: think of package main as the “ignition key” and func main() as turning that key. Without both, the engine — the compiler — refuses to start.
Common Mistakes with package main and func main
One frequent error is using Main or MAIN instead of main. Go is case‑sensitive, and only the all‑lowercase identifier main is recognised as the entry point.
Case Matters:
The function must be spelled exactly func main(). Writing func Main() will compile, but the toolchain will treat the package as a library and refuse to produce an executable. The error message often says “runtime.main_main·f: function main is undeclared in the main package”, which can be confusing if you are looking at a perfectly fine Main().
Another mistake is placing func main() inside a package that is not called main. For instance, if you write package hello and then define func main(), the compiler will not see it as an entry point. The main function only has special meaning when it lives in the main package.
// This will NOT produce an executable.
package hello
func main() {
}
Attempting to build the code above results in something like “package hello is not in GOROOT”, because the compiler does not recognise it as a command. If you actually intended to create a runnable program, you must change the package name to main.
Multiple Files in the main Package
A program can be split across several .go files, as long as they all declare package main and are part of the same directory. Only one file needs to contain the main function. If two files both define func main(), the compiler will stop with a “main redeclared” error. This keeps the entry point unambiguous even in large codebases.
A First "Hello, World" Program
The classic “Hello, World” exercise is the simplest program that combines the entry‑point mechanics with a visible effect. It uses the fmt package from the standard library to write a line of text to the terminal.
Below are the steps to create and run it from scratch. The process works the same way on Linux, macOS, and Windows.
Create a module directory
Every modern Go project starts with a module. Choose a directory and initialise a new module inside it. The module path can be anything; for a learning exercise, a simple name like hello works.
mkdir hello
cd hello
go mod init hello
The go mod init command creates a go.mod file that records the module’s identity and the Go version you are using. You do not need to edit this file for a basic program.
Write the Go source file
Create a file named main.go (the name is conventional but not enforced) and add the following code.
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Every executable starts with package main. The import statement brings in the fmt package, which contains formatted I/O functions. Inside main, fmt.Println writes the string Hello, World! followed by a newline to standard output.
Run the program with go run
The go run command compiles and executes the code in a single step, which is perfect for quick iteration.
go run main.go
You should see Hello, World! printed on your terminal. Behind the scenes, go run builds a temporary executable, runs it, and then cleans it up.
Everything Is Working:
If Hello, World! appears without errors, your Go installation is correctly set up and the program entry point is working as expected.
Build a standalone executable (optional)
To create a permanent binary that you can run directly or share, use go build.
go build
This produces an executable file named hello (or hello.exe on Windows) in the current directory. Run it with ./hello (or hello.exe on Windows) to see the same output. The built binary is self‑contained; it does not need Go installed on the target machine.
What Each Line Does
Even though the program is tiny, every line has a purpose that a beginner should understand.
package main– tells the compiler that this file belongs to themainpackage, making the code buildable as a command.import "fmt"– pulls thefmtpackage from the standard library into scope so thatPrintlncan be used. Without this import, the identifierfmtis undefined and compilation fails.func main() { ... }– declares the entry‑point function. The opening brace{must appear on the same line as the function declaration; Go enforces this through its automatic semicolon‑insertion rules.fmt.Println("Hello, World!")– calls thePrintlnfunction from thefmtpackage.Printlnadds a newline automatically, so the cursor moves to the next line after printing.
Running vs. Building – When to Use Each
The go run command is convenient during development because it skips the separate compilation step. However, it always recompiles the source, which adds a small overhead.
go build produces a binary that you can execute repeatedly without recompilation. Use go run while you are experimenting and making frequent changes; switch to go build when you want to distribute the program or measure its performance.
What Happens If You Make a Mistake
Beginners often encounter a few specific errors when writing their first program.
- “package main is not in GOROOT” or “package … is not a main package”: the file is not using
package main. Check the very first line of your source. - “undefined: fmt”: the
fmtpackage was not imported. Addimport "fmt"above thefunc main()line. - “main redeclared”: you have more than one
mainfunction in the same package. Remove the duplicate or place one of them in a different directory.
No Arguments for main:
You will eventually want to read command‑line arguments or set up signal handling. That happens inside the main function, but the function signature itself never changes. Go uses the os.Args variable and other packages to access runtime information — topics covered later in the standard library sections.
The entry‑point system is the gate through which every runnable Go program passes. Once you understand that package main and func main() are non‑negotiable for commands, you are ready to start writing code that does real work.