Skip to content

Go cheat sheet

Go 1.22+ syntax on one page. Go is statically typed and compiled; run snippets with go run main.go.

29 entries

Basics

package main

import "fmt"

func main() {
    fmt.Println("Hello, Go")
}

Every program starts in package main, func main.

var count int = 10
name := "Ada"     // short declaration (inside functions)
const Pi = 3.14159

Variables, type inference, constants.

var a, b = 1, 2
x, y := y, x

Multiple assignment / swap.

fmt.Printf("%s is %d years\n", name, age)
s := fmt.Sprintf("%.2f", 3.14159)

Formatted output: %v any, %+v struct with names, %T type.

if v, err := strconv.Atoi("42"); err == nil {
    fmt.Println(v)
}

if with an init statement.

for i := 0; i < 3; i++ {}
for cond {}
for {}
for i := range 5 {}   // Go 1.22+

for is the only loop.

switch day {
case "sat", "sun":
    fmt.Println("weekend")
default:
    fmt.Println("weekday")
}

switch: no fallthrough by default.

Slices & maps

nums := []int{1, 2, 3}
nums = append(nums, 4)
part := nums[1:3]

Slices grow with append; slicing shares the backing array.

buf := make([]byte, 0, 64)
len(buf); cap(buf)

make with length and capacity.

for i, v := range nums {
    fmt.Println(i, v)
}

range yields index and value.

ages := map[string]int{"ada": 36}
ages["alan"] = 41
v, ok := ages["bob"]   // ok == false
delete(ages, "ada")

Maps; the comma-ok idiom tests presence.

slices.Sort(nums)
slices.Contains(nums, 3)
maps.Keys(ages)

slices and maps packages (Go 1.21+).

Functions & structs

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("divide by zero")
    }
    return a / b, nil
}

Multiple return values; errors are values.

type User struct {
    Name  string `json:"name"`
    Email string `json:"email,omitempty"`
}
u := User{Name: "Ada"}

Struct with JSON tags.

func (u *User) Rename(n string) { u.Name = n }

Method with a pointer receiver (can modify).

type Shape interface {
    Area() float64
}

Interfaces are satisfied implicitly.

func Map[T, U any](xs []T, f func(T) U) []U {
    out := make([]U, 0, len(xs))
    for _, x := range xs {
        out = append(out, f(x))
    }
    return out
}

Generics (Go 1.18+).

defer file.Close()

defer runs when the function returns (LIFO).

Errors

if err != nil {
    return fmt.Errorf("load config: %w", err)
}

Wrap errors with %w to keep the cause.

if errors.Is(err, os.ErrNotExist) { /* … */ }
var pe *fs.PathError
if errors.As(err, &pe) { /* … */ }

Inspect wrapped errors.

Concurrency

go worker(id)

Start a goroutine.

ch := make(chan int, 10)
ch <- 1
v := <-ch
close(ch)

Buffered channel: send, receive, close.

var wg sync.WaitGroup
for i := range 3 {
    wg.Add(1)
    go func() { defer wg.Done(); work(i) }()
}
wg.Wait()

Wait for goroutines to finish.

select {
case msg := <-ch:
    fmt.Println(msg)
case <-time.After(time.Second):
    fmt.Println("timeout")
}

select waits on several channels.

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

Context for cancellation and deadlines.

var mu sync.Mutex
mu.Lock()
counter++
mu.Unlock()

Protect shared state.

go command

go mod init example.com/app
go get github.com/google/uuid@latest
go mod tidy

Modules and dependencies.

go run .
go build -o app
go test ./...
go vet ./...
gofmt -w .

Run, build, test, vet, format.

GOOS=linux GOARCH=arm64 go build

Cross-compile.

Frequently asked questions

Can I run Go in the browser here?

Not directly; QuickRef runs Python, JavaScript and SQL in the browser. For Go, the official Go Playground (go.dev/play) compiles code on Google’s servers. You can ask the AI code generator to write or explain Go code.

What is the difference between a slice and an array in Go?

An array has a fixed length that is part of its type ([3]int). A slice ([]int) is a view onto an array with a length and capacity, and can grow with append. Almost all Go code uses slices.

Value or pointer receiver?

Use a pointer receiver when the method changes the struct or the struct is large; use a value receiver for small immutable types. Keep receivers consistent across a type’s methods.

Related cheat sheets