Go from the ground up

Your first Go program

What Go is for, the three lines every program starts with, and a first run — on the server here, or with the go command on your own machine.

Part 1 of 12

Beginner12 min readBack to Courses

What Go is for

Go is a small language built for the work behind the scenes: web servers, command-line tools, and services that talk to each other. It compiles to a single file you can copy anywhere, starts instantly, and has concurrency built into the language rather than added by libraries.

The language deliberately leaves things out. There is one loop keyword, one kind of error handling, and no classes. What remains is short enough to hold in your head, which is the trade Go makes: less to write, less to wonder about later.

Every program, at the top

A Go program is organised into packages, and the program that runs is always in package main — that name is how the toolchain knows a package becomes an executable. Inside it there is a function called main, and that is where the program begins.

Everything the program uses is imported by name at the top: import "fmt", the formatting package, is in almost every example because printing is how you see what happened. Imports that go unused are a compile error in Go, which keeps the top of a file honest.

Running it

go run main.go compiles and runs a file in one step — the loop you will live in while learning. go build produces a real executable instead, and that file needs nothing installed to run, not even Go itself.

The formatter is part of the toolchain: gofmt (or go fmt) rewrites your file into one agreed shape — tabs, alignment, spacing. There is no style debate in Go because the tool already decided, and every codebase you open reads the same way.

There is one more command worth knowing early: go vet. It reads the code without running it and reports the mistakes the compiler allows — a Printf call whose format does not match its arguments, a struct tag with a typo, a lock copied by value. go test runs the tests; go vet is the cheaper first look before either.

One program, end to end

package main

import "fmt"

func main() {
	name := "Go"
	year := 2009

	// %s is a string, %d is a whole number.
	fmt.Println("Hello from", name)
	fmt.Printf("The first release was in %d.\n", year)
}

The snippet, line by line

Take the snippet in order. package main says this file belongs to the package that becomes a program. The import names fmt, so every use of fmt.Println later resolves to that package. func main() opens the frame the runtime calls first. name := "Go" declares a string and infers the type; year := 2009 does the same for an int. Println takes the values, separates them with a space and adds a newline. Printf takes a format string and the values it mentions, and %d tells it to print the integer as digits. Nothing is implicit: the format string and the values have to agree. Printf checks them against the verbs at run time, and go vet can catch the same mistake before you run.

Run it, then make it yours

Press Run to see the program build and print. Then change the name and the year, add a third line of your own with Printf, and run it again.

Output
Click "Run" to execute your code

Run the example, then change it. The run goes to a real compiler on the server, so the first one takes a moment while the program is built — after that the round trip is quick.

From source file to running program

The go command is a driver, and go run main.go does three jobs in order: it compiles every package the file imports, links the results with the Go runtime into an executable in a temporary folder, then starts that executable. What you see running is a real binary, not an interpreter walking your text line by line.

Because the compiler reads the whole file before anything runs, it can refuse code that would only misbehave later: a misspelled variable, an import nobody used, a value of the wrong type. go build performs exactly the same checks; the only difference is that it keeps the executable instead of throwing it away.

The runtime is inside that executable too — the scheduler, the garbage collector, and the code behind make and go. That is why a Go binary starts quickly on a machine that has never seen Go, and why copying a single file is a real deployment.

Three things the compiler refuses before your program ever runs: an import that no line uses, a local variable assigned and never read, and a file whose package is not main when you are trying to run it. Each message names a line. Read the first one and fix it — the rest are often consequences of the same mistake.

Try these next

  • Build a line with fmt.Sprintf first, store it in a variable, then print the variable — the same text, assembled in two steps.
  • Add an import you do not use, run the program, and read the error. Remove it and run again.
  • Change year to the string "2009" and watch %d complain at run time, then print it with %s instead.

A receipt you can change

Run it, then add a third item and keep the total correct. Change one price and watch the columns stay lined up.

Output
Click "Run" to execute your code

Check what you learned

One question at a time. A wrong answer explains itself — take another go.

Part 1 of 5

What must a Go program that runs be called?