Where Things Go: Laying Out a Real Repository
The cmd/ and internal/ conventions, the compiler-enforced internal boundary, package naming without stutter, and go.work for multi-module development. Compiled and run against Go 1.26.5.
What it takes to run Go for real — project layout, structured logging with slog, configuration, graceful shutdown, pprof profiling, observability, build and release, go generate, dependency and vulnerability management, containers, the runtime and GC knobs, and reliability patterns — verified against Go 1.26 where it is code.
The cmd/ and internal/ conventions, the compiler-enforced internal boundary, package naming without stutter, and go.work for multi-module development. Compiled and run against Go 1.26.5.
Structured logging with log/slog — text vs JSON handlers, levels and minimum-level filtering, child loggers with With, groups, the allocation-lean LogAttrs path, and the !BADKEY footgun that go vet catches. Compiled and run against Go 1.26.5.
Reading a service's configuration from environment variables, flags, and files, folding them into a single typed Config validated once at startup, with flags-over-env-over-file precedence and a fail-fast on a missing required value. Compiled and run against Go 1.26.5.
Catching SIGTERM with signal.NotifyContext, running ListenAndServe in a goroutine, and calling srv.Shutdown with a bounded timeout so in-flight requests finish instead of dying mid-response. Demonstrated end to end — a slow request survives a signal — and compiled and run against Go 1.26.5.
Profiling Go with the built-in pprof — a real CPU profile captured with runtime/pprof and read with go tool pprof top and list, plus heap, goroutine, and block profiles and the net/http/pprof endpoint. Real profiler output baked in, compiled and run against Go 1.26.5.
The three telemetry signals and what the standard library gives you — slog for logs, expvar publishing counters as JSON at /debug/vars for metrics (run and verified), and OpenTelemetry for traces (described honestly, flagged as not stood up here). Compiled and run against Go 1.26.5.
Cross-compiling a Go binary for another OS and architecture from your laptop, stamping a version into it at link time, producing a static binary with CGO_ENABLED=0, selecting files per platform with build tags, and stripping the result. Compiled and run against Go 1.26.5.
How the //go:generate directive turns a comment into a build step, why go build never runs it, and what running stringer against an int enum actually produces — a committed, reviewable String() method. Compiled and run against Go 1.26.5.
Managing a module's dependencies with go.mod and go.sum, minimal version selection, go mod tidy and vendor, and govulncheck — which flags only the vulnerabilities your code actually reaches. Compiled and run against Go 1.26.5.
Containerizing a Go service with a multi-stage Dockerfile — a full builder stage, then a static CGO-free binary copied into distroless or scratch, with CA certs, a non-root user, and a .dockerignore. The static-binary proof is run; the image is actually built. Go 1.26.5.
How the Go runtime decides stack versus heap, what GOGC and GOMEMLIMIT actually control, why GOMAXPROCS matters in a container, and when sync.Pool earns its keep — measured, not guessed. Compiled and run against Go 1.26.5.
Liveness, readiness, and startup probes and why an orchestrator needs three different answers — a cheap /healthz that means 'restart me' and a /readyz that means 'stop routing to me' — plus the production move of flipping readiness off on SIGTERM before draining. Compiled and run against Go 1.26.5.
The patterns that keep a Go service standing when its dependencies don't — context deadlines on every call, retries with exponential backoff and jitter, rate limiting with x/time/rate, a circuit breaker, and panic recovery — each one built and run. Compiled and run against Go 1.26.5.