the short answer
Every runnable Go program has the same frame. It starts with package main, then import lines for the packages it uses, such as fmt for printing. Then comes func main(), where the program starts running. Your own functions, constants and variables can sit outside main, but instructions that do something must be inside a function.
Every runnable Go program has the same frame. It names its package, lists the packages it imports, and has a function called main where the program starts:
package main
import "fmt"
func main() {
fmt.Println("Hello, Go!")
}Hello, Go!Every Go program you write will start this way. This guide goes through the frame line by line, then shows where your own functions, constants and variables fit, and the rules Go is strict about. Every example runs right here in your browser.
The frame, line by line
package main
Go code is organised into packages, which are groups of related code. The first line of every Go file says which package it belongs to. The name main is special: it tells Go that this package is a program you can run, rather than a library for other programs to use.
import "fmt"
import brings in another package so you can use what it offers. fmt, short for format, has the functions for printing text. To use one of them, write the package name, a dot, then the function name: fmt.Println.
func main()
func starts a function. The function called main is where the program starts, and when main reaches its closing curly bracket, the program ends. Your instructions go between the brackets, one per line, with no semicolons needed.
Notice the capital P in Println. In Go, a name that starts with a capital letter can be used from other packages. Println is shared by fmt for everyone to use, so it starts with a capital.
Importing more than one package
To import several packages, put them in brackets, one per line:
package main
import (
"fmt"
"strings"
)
func shout(word string) string {
return strings.ToUpper(word) + "!"
}
func main() {
fmt.Println(shout("hello"))
fmt.Println(shout("go"))
}HELLO!
GO!shout is a function of our own, written outside main. It takes a string and gives one back, made with strings.ToUpper from the strings package. main calls it twice and prints each answer.
Functions can go in any order
Go reads the whole file before it runs anything. So main can call a function that is written further down:
package main
import "fmt"
func main() {
fmt.Println(double(21))
}
func double(n int) int {
return n * 2
}42Many Go programmers put main first so readers see the big picture straight away. Others put it last. Go is happy either way.
What can go outside main
Constants and variables can be made at the top level of the file, outside any function. Every function in the package can then use them:
package main
import "fmt"
const greeting = "Welcome"
var visits = 0
func main() {
visits = visits + 1
fmt.Println(greeting, "- visit number", visits)
}Welcome - visit number 1fmt.Println puts a space between each of the things you give it, which is why the words come out spaced.
Instructions are different. A line that does something, like printing, must live inside a function:
package main
import "fmt"
fmt.Println("Hello")
func main() {
}line 5: syntax error: non-declaration statement outside function bodyThe same goes for the short way of making a variable, :=. It only works inside functions. At the top level, write var instead.
init runs before main
A function called init runs by itself, before main:
package main
import "fmt"
func init() {
fmt.Println("init runs first")
}
func main() {
fmt.Println("then main")
}init runs first
then mainMost beginner programs never need init, but now you know what it is when you meet it in other people’s code.
The whole layout, top to bottom
Put together, a Go file follows this order:
- The package line, always first.
- The imports, straight after it.
- Everything else at the top level, in any order you like: constants, variables, types such as structs, and functions.
- func main, somewhere among those functions, in exactly one file of the package.
Inside each function, instructions run from top to bottom. Outside functions, only declarations are allowed: lines that make something, not lines that do something.
Common mistakes
Go is stricter than many languages about the shape of a program. These are the rules that catch people out.
The opening bracket on its own line
package main
import "fmt"
func main()
{
fmt.Println("Hello")
}line 5: missing function bodyGo adds invisible semicolons at the end of certain lines, including a line that ends with a closing bracket like main(). So Go reads func main(); as a function with no body, and the { on the next line is left on its own. Keep the opening bracket at the end of the func line.
An import you do not use
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println("Hello")
}line 5: imported and not used: "strings"In most languages an unused import is harmless. In Go it is an error. Delete the line, or use the package. Newer versions of Go word this message slightly differently, but the meaning is the same.
A variable you do not use
package main
import "fmt"
func main() {
name := "Ava"
fmt.Println("Hello")
}line 6: name declared but not usedThe same rule applies to variables made inside functions. An unused variable is often a sign that something was forgotten, so Go makes you deal with it.
A small letter on Println
package main
import "fmt"
func main() {
fmt.println("Hello")
}line 6: cannot refer to unexported name fmt.printlnUnexported means kept private to its own package. Names that start with a small letter cannot be used from outside, so fmt has nothing called println for you to use.
Forgetting func main
package main
import "fmt"
func start() {
fmt.Println("Hello")
}runtime.main_main·f: function main is undeclared in the main packageThe program compiles, but Go has nowhere to start. The same happens the other way round: change package main to any other name and the program cannot run at all.
Running Go on your own computer
Once Go is installed, save the frame in a file called main.go and type go run main.go in a terminal. For anything bigger than one file, start a module first. In a new folder, run go mod init followed by a name for your project. That creates a go.mod file, which records the project’s name and the version of Go it uses.
Run go fmt and Go lays your code out in its standard style, with tabs for indenting. Because so much Go code is formatted by this one tool, code from different people tends to look alike, which makes it easier to read.
A short exercise
This program should print Total: 7, but it has three problems. Run it and fix the first error. Go shows one problem at a time here, so each fix uncovers the next.
package main
import (
"fmt"
"os"
)
func add(a int, b int) int {
return a + b
}
func main()
{
total := add(3, 4)
fmt.println("Total:", total)
}line 12: missing function bodyTo make your fixes, copy the code into the playground from the button at the bottom of the page and choose Go.
One possible answer
package main
import "fmt"
func add(a int, b int) int {
return a + b
}
func main() {
total := add(3, 4)
fmt.Println("Total:", total)
}Total: 7The three fixes: move the opening bracket up to the func line, remove the unused os import, and give Println its capital P.
Related reading
- Java’s main method explained, for how Java starts a program in its own main method.
- What does a computer program do?, for the idea of a program running its instructions in order.
Your next step
The frame becomes second nature after a handful of programs. Gwecode’s Go Level 1 starts with this exact frame in its first lesson, then adds variables, decisions, loops, slices, functions and structs, one short lesson at a time. You finish by building a funfair token counter that puts it all together. Every lesson is free and runs in your browser. Create a free account to keep your progress, and write your first line below.
practise this · go · lessonYour first linestart the lessonquestions
Why does Go complain about unused imports and variables?
Go treats them as errors on purpose. An unused variable is often a sign of a mistake, and unused imports make programs slower to build. Delete what you do not use, or use it.
Does the opening curly bracket have to be on the same line?
Yes. Go adds invisible semicolons at the ends of some lines, and a bracket on the next line gets cut off from the line before it. Keep { at the end of the func line.
What is package main for?
It tells Go that this package is a program you can run, rather than a library for other code to use. A program needs package main with a func main inside it.
Can a Go program have more than one file?
Yes. Bigger programs split their code over many files in the same folder, each starting with the same package line. Only one func main is allowed in the whole package.
What does go fmt do?
It rewrites your code in Go’s standard layout, with tabs for indenting and spaces in the usual places. It comes with Go, and many code editors run it every time you save.
