Part 0 · 2 chapters · ~12 min

Basics

Installing Go and a first module, packages and visibility, variables, constants and zero values, functions with multiple returns, control flow, slices and maps, structs, the standard library tour, formatting with gofmt, and building and cross-compiling a binary.

1

Modules, packages and a first program

code
mkdir ledger && cd ledger && go mod init bank.example/ledger

// main.go
package main

import (
	"fmt"
	"os"
)

func fee(amountKobo int64) (int64, error) {           // multiple return values: result and error
	if amountKobo <= 0 { return 0, fmt.Errorf("amount must be positive, got %d", amountKobo) }
	f := amountKobo * 50 / 10_000                       // 0.5%
	return max(f, 1_000), nil                           // built-in max (Go 1.21+); minimum ₦10
}

func main() {
	f, err := fee(5_000_000)
	if err != nil { fmt.Fprintln(os.Stderr, err); os.Exit(1) }
	fmt.Printf("fee: %d kobo\n", f)                    // fee: 25000 kobo
}

go run .            go build -o ledger .            GOOS=linux GOARCH=amd64 go build -o ledger-linux .
A GO PROGRAM
modules, packages, files, and one entry point
go.modmodule bank.example/ledger, go 1.23, dependenciespackagesone directory = one package; exported names start with a capitalimportsstandard library first; no unused imports allowedpackage main + func main()the entry point of a binarygo buildone static binary, cross-compiled with GOOS/GOARCH
swipe the figure sideways, or tap expand for full screen
1/5
modules
A module (go.mod) is a versioned collection of packages with its dependencies pinned in go.sum. go mod init creates it.
go.mod + go.sumgo mod init bank.example/ledger
2

Slices, maps, structs and zero values

code
var count int           // zero values: 0, "", false, nil; no uninitialised memory ever
names := []string{"Ada", "Bayo"}          // a slice: pointer, length, capacity over an array
names = append(names, "Chi")             // may reallocate (amortised O(1), DSA part 0)
balances := map[string]int64{"ada": 500_000}
if b, ok := balances["bayo"]; !ok { _ = b }  // comma-ok: distinguishes missing from zero

type Account struct {
	ID        string
	OwnerID   string
	Balance   int64           // kobo
	CreatedAt time.Time
}
acct := Account{ID: "ac_1", OwnerID: "u_7"}   // unspecified fields get zero values
a slice gotcha
Two slices can share one backing array: b := a[:2]; b = append(b, 99) may overwrite a[2]. When you keep a sub-slice long term, copy it (slices.Clone).