Go — Reference

Source: https://go.dev/doc/

Go

  • Created: 2009 by Robert Griesemer, Rob Pike, Ken Thompson at Google
  • Latest stable: Go 1.26.2 (April 2026); Go 1.26.0 released 2026-02-10
  • Paradigms: imperative, concurrent, structurally-typed, lightly object-oriented (no inheritance), generic (since 1.18)
  • Typing: static, strong, structural for interfaces, type inference at declaration
  • Memory: GC (concurrent low-latency tri-color mark-sweep, sub-ms STW)
  • Compilation: AOT to single static native binary; very fast compile times; no runtime dependency on libc by default
  • Primary domains: backend services, microservices, CLI tools, infrastructure (Docker, Kubernetes, Terraform), networking, observability, build tooling
  • Official docs: https://go.dev/doc/

1. At a glance

  • Stewarded by the Go team at Google, governed by the open-source proposal process on GitHub.
  • 6-month release cadence (February + August). Go 1.x is stable: the Go 1 compatibility promise means working code keeps compiling.
  • One implementation: gc (the official compiler). gccgo exists but is not actively developed at the same pace. TinyGo for embedded/WASM.
  • Cross-compilation is built in: GOOS=linux GOARCH=arm64 go build.

2. Getting started

  • Install: Official tarball/installer at https://go.dev/dl/. Linux: extract to /usr/local/go, add to PATH. macOS: brew install go. Windows: winget install GoLang.Go or MSI.

  • Version manager: none official. g (https://github.com/stefanmaric/g), gvm, asdf. Or go install golang.org/dl/go1.26@latest && go1.26 download.

  • Hello, world:

    package main
    import "fmt"
    func main() { fmt.Println("Hello, world!") }

    Run: go run . or go build -o hello && ./hello.

  • Project layout: go.mod at module root; cmd/<name>/main.go for binaries, internal/ for non-exported packages, pkg/ (rare) for reusable libs.

  • Build tool: go CLI is everything: go build, go test, go run, go install, go mod, go work, go vet, go fmt, go generate, go tool pprof, go tool trace.

  • REPL/playground: The Go Playground (https://go.dev/play/) — sandboxed, sharable. gore (community REPL).

3. Basics

  • Primitives: bool, string, int/int8/int16/int32/int64, uint*, uintptr, byte (=uint8), rune (=int32 Unicode codepoint), float32/float64, complex64/complex128. Literals: 0x, 0b, 0o, _ separators (Go 1.13+), backtick raw strings.
  • Variables: var x int = 1, short declaration x := 1, const, iota for enum-like sequences. Block scope. No unused imports/variables (compile error).
  • Control flow: if/else (with init: if v, err := f(); err == nil { ... }), switch (no fallthrough by default; switch x.(type) for type switch), for (only loop keyword: for i := 0; i < n; i++, for cond, for { }, for k, v := range coll), goto (rare). range over functions (Go 1.23+) for custom iterators.
  • Functions: multiple return values (func f() (int, error)), named returns, variadic func f(xs ...int), closures, first-class. Methods are functions with a receiver: func (r Rect) Area() float64.
  • Strings: immutable UTF-8 byte sequences. Indexing returns bytes; for i, r := range s iterates runes. No interpolation; use fmt.Sprintf("%v %v", a, b). strings.Builder for efficient concat.
  • Collections: arrays [N]T, slices []T (the workhorse), maps map[K]V, channels chan T. No tuples (use multiple returns or structs). No sets (use map[T]struct{}).

4. Intermediate

  • Generics (1.18+): func Map[T, U any](s []T, f func(T) U) []U. Type sets via interfaces with ~int | ~float64. any is alias for interface{}. comparable built-in constraint.
  • Modules/packages: go mod is the dependency system. Module = repo + go.mod; package = directory of .go files with same package decl. Workspaces (go.work, 1.18+) for multi-module.
  • Error handling: errors are values. Convention: func f() (T, error); check if err != nil. errors.Is / errors.As for wrapping (Go 1.13+); fmt.Errorf("...: %w", err). panic/recover for unrecoverable; not for control flow.
  • Concurrency: goroutines (go f() — multiplexed onto OS threads by GMP scheduler), channels (ch := make(chan T), <-ch send/receive), select for multiplexing, sync.WaitGroup, sync.Mutex/RWMutex, sync.Once, sync.Map, sync/atomic, context.Context for deadlines/cancellation.
  • I/O & networking: os, io, bufio, io/fs (1.16+), os/exec, net (TCP/UDP/Unix), net/http (production-grade server in stdlib), crypto/tls, database/sql. net/http.ServeMux got pattern matching with method+host in 1.22.
  • Stdlib highlights: context, encoding/json, encoding/json/v2 (1.25+ experimental), time, log/slog (structured logging, 1.21+), slices, maps, cmp (1.21+), iter (1.23+), crypto/*, regexp, text/template/html/template, embed, testing.

5. Advanced

  • Memory & GC: generational-ish concurrent tri-color mark-sweep with write barrier; goal is sub-millisecond stop-the-world. Tune via GOGC (target heap growth %, default 100), GOMEMLIMIT (1.19+, soft memory ceiling). runtime/debug.SetGCPercent, SetMemoryLimit.
  • Concurrency deep dive: GMP scheduler — Goroutines (G) multiplexed onto Logical Processors (P), executed on OS threads (M). Work-stealing. runtime.GOMAXPROCS controls P count. Goroutines start with 8 KiB stack, grow as needed (segmented then contiguous). runtime.LockOSThread for cgo / GUI loops. Race detector: go run -race.
  • FFI/interop: cgo (import "C" + // #include <foo.h> comment). Crossing the cgo boundary is expensive (~150 ns each way) and breaks goroutine scheduling on that thread. go:linkname to access unexported symbols, go:noescape to lie about pointer escape. WebAssembly target (GOOS=js GOARCH=wasm and GOOS=wasip1).
  • Reflection: reflect package — reflect.TypeOf, reflect.ValueOf, Kind(). Used by encoding/json, text/template. Slow; codegen via go generate is preferred for hot paths.
  • Performance tooling: pprof (CPU, heap, allocs, block, mutex, goroutine profiles via net/http/pprof), go tool trace (execution traces), go test -bench + testing.B, -race, -cpuprofile/-memprofile, go test -gcflags='-m' for escape-analysis output, benchstat for comparing benchmarks. PGO (1.21+ stable): go build -pgo=default.pgo.

6. God mode

  • Assembly: Go’s own asm dialect (Plan 9 derived); per-arch files like foo_amd64.s. Used in runtime, crypto, math/big for SIMD.
  • Runtime scheduler internals: GMP, run queues (per-P local + global), netpoller (epoll/kqueue/IOCP), sysmon thread, preemption (signal-based since 1.14). Read runtime/proc.go.
  • Escape analysis: decides stack vs heap. Inspect with go build -gcflags='-m -m'. Make values escape (hide intent from compiler) only when necessary.
  • unsafe.Pointer rules: six legal conversion patterns (see unsafe docs). Anything else is unsafe and may break.
  • Build tags: //go:build linux && amd64 constraints; file-name suffixes (foo_linux_amd64.go).
  • plugin package: Linux/macOS only, ELF/Mach-O dlopen — fragile across Go versions, rarely used in practice.
  • Generics introspection: limited reflection on type parameters; code-shape-shared instantiation (GCShape) means one binary, runtime dictionary lookup.
  • Race detector internals: built on ThreadSanitizer (TSan) with happens-before tracking via vector clocks.
  • Compiler directives: //go:noescape, //go:linkname, //go:noinline, //go:nosplit, //go:nowritebarrier, //go:embed (1.16+), //go:generate.
  • Profile-guided optimization: default.pgo next to main package auto-detected (1.21+). Typical 2-7% wins.
  • Embedding the runtime: Go can be embedded into other languages via c-shared/c-archive build modes (go build -buildmode=c-shared).
  • TinyGo for microcontrollers / WASM with much smaller runtime; uses LLVM backend.

7. Idioms & style

  • Naming: MixedCaps (PascalCase) for exported, mixedCaps for unexported. Acronyms uppercase: URL, ID, HTTP. Short receiver names (r *Rect). Package names lowercase, single word, no underscores.
  • Formatter: gofmt (and goimports) — non-negotiable; CI rejects unformatted code. Linter: go vet (built-in), staticcheck (the canonical extra linter), golangci-lint (aggregator).
  • Idiomatic Go: “accept interfaces, return structs”; small interfaces (often single-method like io.Reader); errors are values, handle them at every layer; one-letter-ish receiver names; explicit if err != nil; favor composition over inheritance (Go has no inheritance); use channels to share memory by communicating, not memory to share state. Effective Go is the canonical doc.
  • Reviewers look for: unhandled errors, mutex without defer Unlock, goroutine leaks (no cancellation), unbuffered channel deadlocks, context.Context not first param, package-level mutable state, premature abstraction.

8. Ecosystem

  • Web: stdlib net/http is production-grade. Gin, Echo, Fiber, Chi, Gorilla, Huma. gRPC-Go, connectrpc/connect-go.
  • DB: database/sql + drivers (pgx, go-sql-driver/mysql, mattn/go-sqlite3); GORM, sqlc (codegen from SQL), ent, bun, squirrel.
  • CLI: Cobra, Viper, urfave/cli, kong.
  • Cloud/infra: Kubernetes, Terraform, Docker, etcd, Prometheus, Vault, Consul, Cilium, Helm, Caddy — all written in Go.
  • Testing: stdlib testing + testing/quick; testify (assertions/mocks), gomock, counterfeiter, gotestsum, gomega/ginkgo (BDD).
  • Doc tools: go doc + pkg.go.dev (auto-published from Git tags).
  • Notable users: Google, Cloudflare, Uber, Twitch, Dropbox, Netflix, MongoDB, Meta, Microsoft (Azure), HashiCorp.

9. Gotchas

  • nil interface vs interface holding typed nil: var p *Foo = nil; var i Foo = p; i == nil returns false. Source of constant bugs.
  • Loop variable capture (fixed in 1.22): before 1.22, for i := range xs { go func() { use(i) }() } shared i. Fixed: each iteration has its own.
  • Slices share backing arrays: s2 := s1[2:5] mutates s1. Append may or may not reallocate; rely on returned slice.
  • map iteration order is randomized; do not depend on order.
  • time.Now() includes monotonic clock; serializing across the wire loses it.
  • No generics for methods, only top-level functions and type definitions (1.21 still has limits).
  • defer in a long loop queues N callbacks; can OOM.
  • Goroutine leaks from forgotten <-ch receives or missing context.Done() selects.
  • init() runs at package load; ordering is per-file alphabetical, then deps; surprising side effects.
  • json.Marshal errors on cyclic types and unexported fields silently.
  • http.DefaultClient has no timeout — set one or you’ll wait forever.
  • new(T) vs &T{}: prefer &T{}; same effect, more idiomatic.
  • Capitalization controls visibility — rename a field from Name to name and you’ve broken JSON marshaling and your public API.

10. Citations