Week 1 - The Toolchain and the Build Pipeline¶
1.1 Conceptual Core¶
- The Go toolchain is a single binary that bundles the compiler, linker, formatter, dependency manager, test runner, race detector, profiler, and tracer. Every other ecosystem you've used distributes these as separate tools; Go's choice to integrate them is itself a design statement.
go buildis not just a compiler invocation. It is a dependency graph walker that:- Resolves the module graph (
go.mod+go.sum). - Computes the build action graph (run with
go build -xorgo build -nto inspect). - Compiles each package to an archive (
.a) cached in$GOCACHE(default$HOME/.cache/go-build). - Links into a final binary or
.so/.a. - The build cache is content-addressed. Identical inputs → identical outputs → cache hit. This is what makes
go buildfeel instantaneous on second invocations.
1.2 Mechanical Detail¶
- Module mode is the only mode. GOPATH mode is dead-do not start a project under
$GOPATH/srcin 2026. go.moddirectives:module,go,toolchain,require,replace,exclude,retract. Memorize all of them.- Minimum Version Selection (MVS): Go's resolver picks the minimum version of each dependency that satisfies all
requiredirectives. This is the opposite of npm/pip "latest compatible." Read Russ Cox's MVS paper. go.sumis a content-addressed integrity ledger, not a lock file. It records hashes of every module version ever depended on, including transitively-dropped versions. Never edit by hand.- The
vendor/directory: dead in OSS, alive in air-gapped enterprise. Usego mod vendoronly when offline builds are mandatory. - Useful introspection commands:
- `go env - every environment variable the toolchain consults.
- `go list -m all - every module in the build.
- `go list -deps -json ./... - the package graph as JSON.
- `go version -m
- the modules embedded in a built binary (BuildInfo).
1.3 Lab-"Hello World, Audited"¶
- Create
hello-audited. Setgo 1.22and atoolchain go1.22.xdirective. - Build with
go build -trimpath -ldflags="-s -w -X main.version=v0.1.0". Rungo version -m ./hello-audited. - Strip with
stripand compare. Cross-compile tolinux/arm64,darwin/arm64,windows/amd64withGOOS=... GOARCH=... go build. - Document the size delta from each flag in
NOTES.md. - s -wtypically saves ~30%; - trimpathis a reproducibility flag (no local paths in the binary), not a size flag. - Inspect the binary with
go tool nmandgo tool objdump. Identify the runtime symbols (runtime.main,runtime.gcStart,runtime.schedule).
1.4 Idiomatic & golangci-lint Drill¶
- Install
golangci-lint. Enable a strict config:errcheck,govet,staticcheck,gosimple,ineffassign,revive,gocritic,gosec,bodyclose,nilerr,prealloc,unconvert. Run on a small repo. Read each finding's URL and understand the rationale.
1.5 Production Hardening Slice¶
- Add a
Makefile(orTaskfile.yml) target that runsgofmt -l -d,go vet ./...,golangci-lint run,go test -race -count=1 ./...,go build -trimpath. This is the baseline CI invocation; every subsequent week's hardening slice extends it. - Adopt
go-licensesto scan dependency licenses. Commit the report.