Skip to content

Language guide

Learn Go

A simple compiled language built for servers, tools and cloud infrastructure.

Go on SkillAIVibe

Runs in your browser

Real Go runs inside a sandbox in your own browser — yaegi (commit fcb76d1e) — an interpreter, not a compiler; Go 1.21/1.22 stdlib ceiling. Nothing you write is sent to a server. Last verified against the sandbox's checks on .

10 exercises in order, each teaching exactly one new idea. Every one runs in this tab, checks your output, and explains what went wrong in plain language.

  1. Library Due-Date ReminderDeclaring variables with := and printing them with fmt.Println and fmt.Printf, including a format string that must end with \n
  2. Recipe ScalerArithmetic on ints with +, -, *, and /, including that integer division truncates instead of rounding (7 / 2 is 3)
  3. Parking Meter StatusBranching with if / else if / else and comparison operators (<=, etc.)
  4. Bus TimetableCounting for loops (for i := 0; i < n; i++) that compute a new value on each pass
  5. Poem Word CounterReading a line with bufio, cleaning it with strings.TrimSpace, and splitting it into words with strings.Fields
  6. Tool Shed InventorySlices: literals, growing one with append (and keeping its result), indexing, and len() inside a loop
  7. Currency ConverterMaps: map[string]float64 literals, looking values up by key (including the zero-value gotcha for a missing key), and formatting floats with %.2f
  8. Board Game LeaderboardWriting and calling a function with a parameter and a return value: func highestScore(scores []int) int
  9. Playlist RuntimeDefining a struct with fields and a method on it (func (s Song) Format() string), used across a slice of structs
  10. Tip Jar SplitCombining a struct, a helper function, and a loop to compute a proportional split with float formatting (%.1f and %.2f)

What Go is

Go is a compiled language created at Google with a deliberately small feature set: one kind of loop, no classes, no exceptions, and a formatter that ends arguments about style. Writing it feels plain and explicit — errors are returned as ordinary values and checked with an if, and the compiler refuses to build a program that has an unused variable or import. The reward is that Go code is easy to read months later, compiles quickly to a single executable, and handles many things at once with goroutines and channels.

Where Go is used

Cloud infrastructure and DevOps tooling
Docker, Kubernetes and Terraform are written in Go, as are many of the command-line tools used to operate them.
Web servers and APIs
The standard library's net/http package is enough to build a production HTTP server without a framework, which is why a lot of backend services are Go.
Command-line tools
A Go program compiles to one self-contained binary with no runtime to install, which makes it a natural fit for tools that have to run on someone else's machine.
Network services and proxies
Programs that hold a large number of connections open at once — proxies, load balancers, chat servers — lean on goroutines, which cost far less than operating-system threads.
Databases and storage systems
CockroachDB, etcd and Prometheus are written in Go; the pattern of a fast, concurrent, self-contained server suits that kind of software.

Your first Go program

Saved as hello.go. You can paste it straight into the playground to see it run.

Go
package main

import "fmt"

func main() {
	name := "Asha"
	steps := 4
	fmt.Println(name, "took", steps, "steps.")
	fmt.Printf("Twice that is %d.\n", steps*2)
}

What it prints

Output
Asha took 4 steps.
Twice that is 8.
  1. Line 1 says which package this file belongs to. A program that can be run on its own must be in package main.
  2. Line 3 imports fmt, the standard-library package for formatted printing. Go refuses to compile a file that imports something it does not use, so every import is there because it is needed.
  3. Line 5 begins main, the function every Go program starts in. The opening brace has to be on the same line as func; putting it on the next line is a compile error, and gofmt would have moved it back anyway.
  4. Lines 6 and 7 declare variables with :=, which declares and assigns in one step and lets Go work out the type: name becomes a string and steps an int. The indentation is a tab because that is what gofmt uses.
  5. Line 8 prints with Println, which takes any number of values, puts a single space between each of them and adds a newline at the end. That is why the output reads naturally without any spaces inside the quoted pieces.
  6. Line 9 uses Printf for formatted output: %d is a placeholder for an integer, filled by steps*2, and the \n at the end is needed because Printf does not add a newline for you.

Try it in the Go playground →

Run Go on your own computer

Go's toolchain is one download containing the compiler, formatter, test runner and package manager, all behind a single go command. There is nothing else to install.

  1. Install Go

    Download the installer for your platform from go.dev/dl and run it. Linux users can use their distribution's package instead, but the version there is sometimes behind; the official download is a tar archive you unpack into /usr/local. Any release that is still supported works for everything on this site.

  2. Check it works

    Open a new terminal, because the installer edits your PATH and terminals that were already open may not see the change, then confirm the version prints.

    Shell
    go version
  3. Create a module

    Make a folder for the program, move into it, and run this once. It writes a go.mod file that names the module. A single-file program does not strictly need one, but every Go project has one, and it becomes required the moment you import anything outside the standard library.

    Shell
    go mod init hello
  4. Save the file and run it

    Save the program as hello.go in that folder and run it. go run compiles to a temporary location and runs the result in one step, so it feels like an interpreter even though it is not. To produce an executable you can keep or copy elsewhere, use go build instead, which writes a file named after the module.

    Shell
    go run .
  5. Format on save

    Go has one official style and gofmt applies it. Run it by hand, or better, set your editor to run it on save: the Go extension for VS Code and the gopls language server do this automatically.

    Shell
    gofmt -w hello.go

A learning order for Go

Stages, not a timetable. Each one exists because the next would not make sense without it, and how long each takes depends on how much you write.

  1. Stage 1. Packages, printing and variables

    • package main and func main
    • fmt.Println and fmt.Printf
    • var and :=
    • int, float64, string and bool
    • constants

    Go's strictness shows up immediately — an unused variable stops the build — so the first stage is partly about learning to appreciate a compiler that says no.

  2. Stage 2. Control flow and functions

    • if, including the optional init statement
    • the single for loop in its three forms
    • switch
    • functions with multiple return values
    • defer

    Multiple return values are the basis of Go's error handling, and the for loop is the only loop there is. Both are small ideas that shape everything written afterwards.

  3. Stage 3. Slices, maps and structs

    • arrays versus slices
    • append and len
    • maps
    • range loops
    • structs and methods

    Slices are the everyday collection and have some non-obvious behaviour around sharing an underlying array. Structs with methods are how Go organises data without classes.

  4. Stage 4. Errors and interfaces

    • the error type and if err != nil
    • errors.New and fmt.Errorf
    • wrapping, errors.Is and errors.As
    • interfaces and implicit satisfaction
    • pointers and pointer receivers

    Go's error handling is explicit and repetitive on purpose. Interfaces are satisfied without declaring it, which is unlike most languages and is what makes the standard library so easy to compose.

  5. Stage 5. Concurrency

    • goroutines
    • channels
    • select
    • sync.WaitGroup and sync.Mutex
    • context for cancellation

    Concurrency is the reason many teams choose Go, and its tools are simple to start with and subtle to use well. Learn it after the basics, not before; a data race is much easier to understand once slices and pointers are second nature.

  6. Stage 6. Tooling and a real project

    • go test and table-driven tests
    • modules and go get
    • net/http, encoding/json and os
    • go vet and the race detector
    • structuring a multi-package project

    Testing and the standard library are built in, so a first real project — an HTTP service or a command-line tool — needs almost nothing from outside the toolchain.

Mistakes beginners make in Go

Declaring a variable and not using it
Go stops the build with 'declared and not used: x'. It is not a warning you can ignore; the program will not compile. The same rule applies to imports, which fail with '"os" imported and not used'. Delete the variable, or assign it to the blank identifier _ while you are experimenting.
Using := when you meant =
Inside an if or a loop, err := doSomething() creates a new variable that shadows the outer err, so the outer one never changes and your error check silently looks at the wrong value. The compiler allows it. When a variable already exists in scope, assign with =; use := only to declare.
Writing to a map that was never made
Declaring var counts map[string]int gives you a nil map. Reading from it is fine and returns zero values, but writing to it panics with 'panic: assignment to entry in nil map'. Create the map with make(map[string]int) or a literal before writing. The same family of error, 'invalid memory address or nil pointer dereference', comes from calling a method through a nil pointer.
Ignoring the error return
result, _ := strconv.Atoi(text) compiles and quietly gives you 0 when text is not a number. Go does not force you to check errors; the convention is that you always do, immediately, with if err != nil. Throwing the error away is a common way for a Go program to hide a bug until much later.
Assuming a slice is an independent copy
b := a[1:3] shares the same underlying array as a, so writing to b changes a. Whether append allocates a fresh array depends on the slice's capacity, which can make the behaviour look random. Use copy when you need a slice that is genuinely separate.

Strengths and trade-offs

Where it is strong

  • A small language you can hold in your head: the specification is short, there is usually one way to do something, and code written by strangers looks like your own.
  • Quick compiles and a single static binary, so deploying a Go program means copying one file.
  • Concurrency built into the language with goroutines and channels rather than bolted on as a library.
  • The standard library covers HTTP servers, JSON, testing, cryptography and templating, so many programs need no third-party packages at all.

Where it is not

  • Verbose error handling: if err != nil { return err } appears after almost every call, and there is no shorter form.
  • Deliberately limited: no classes or inheritance, generics only since Go 1.18 and simpler than in most other languages, and no exceptions. People who like expressive type systems find it plain.
  • Garbage collected, so it is not for kernels, firmware or code with hard latency limits, where C, C++ or Rust are used.
  • Not the language for graphical desktop apps, mobile apps or code running in the browser; its home is servers and command-line tools.

Who Go is for

Go is a good choice for a beginner who wants to build servers, command-line tools or cloud infrastructure, and a good second language for anyone who already knows Python or JavaScript and wants static types and real concurrency without the weight of C++ or Rust. Its rigidity — the compiler rejecting unused variables, the single loop, the mandatory formatting — is a feature for learners, because there is little style to argue about and one clear way to write most things. Look elsewhere if you want to make games, mobile apps or web front-ends, or if you want a language that lets you express elaborate type relationships; Go asks you to write things out plainly instead.

Questions about learning Go

Is Go a good first language?
It can be, especially if you want to build things that run on servers. The syntax is small, the toolchain is one download, and the compiler's strictness catches mistakes early. What makes it slightly harder than Python as a first language is the amount of explicit error checking and the lack of an interactive prompt: you write a file and run it every time. If your interest is data, scripting or programming in general, Python first is the easier road; if your interest is backend systems, Go first is a reasonable choice.
Why does the compiler refuse an unused variable or import?
Because Go treats them as errors rather than warnings, on purpose: an unused variable is usually a mistake or a leftover, and an unused import slows the build and hides what the file depends on. The fix is to delete it or, while experimenting, assign the value to the blank identifier _. Editors that use gopls remove unused imports automatically when you save.
Is Go the same thing as Golang?
Yes. The language is called Go; 'golang' comes from the address of its original website, golang.org, which has since moved to go.dev, and the word survives because 'go' on its own is hard to search for. In writing, call it Go.
Does Go have classes?
No. Go has structs, which hold data, and methods, which are functions attached to a type. There is no inheritance; reuse comes from embedding one struct in another and from interfaces, which a type satisfies simply by having the right methods. People coming from Java or C# usually find this odd at first and then find it simpler.

The primary source

When this guide and the official documentation disagree, the documentation is right and we would like to hear about it.

Other languages

All languages and paths · Programming glossary · Your progress