Go Cookbook
“How would you do X?” — practical, production-ready recipes with the approach, full code, pitfalls and variations.
Go
- Benchmark code with testing.B.LoopYou want to know whether an optimisation helps and how many allocations it makes.
- Build a small, secure container image for a Go serviceGo images are large, run as root and include build tools.
- Decode and validate JSON request bodies safelyHandlers accept huge bodies, unknown fields and invalid values without complaint.
- Embed static files and templates in the binaryDeployments break because templates or assets aren't copied next to the binary.
- Load and validate configuration from environment variablesConfiguration is read ad hoc with os.Getenv all over the code, and typos are discovered in production.
- Log structured JSON with slog and redact secretsLogs are unstructured strings, and tokens or passwords end up in them.
- Process jobs concurrently with a bounded worker poolSpawning a goroutine per item overwhelms dependencies; processing sequentially is too slow.
- Profile a running service with pprofCPU or memory usage climbs in production and you need to see where.
- Rate limit requests per clientOne client sends bursts that degrade the service for everyone.
- Retry operations with exponential backoff and jitterTemporary failures (timeouts, 503s) fail requests that would succeed a moment later.
- Route HTTP requests with the standard library ServeMuxYou want method-based routes and path parameters without adding a router dependency.
- Run database transactions with database/sqlMulti-step writes leave partial data when one step fails, and connections leak.
- Shut down an HTTP server gracefullyDeploys kill the process mid-request, dropping connections and losing work.
- Stream results with range-over-func iteratorsPaginated APIs or database rows are loaded fully into memory before processing.
- Test HTTP handlers with httptestHandler tests start real servers on ports or skip routing and middleware.
- Use context deadlines for outbound callsA slow dependency makes requests pile up because calls never time out.
- Wrap, inspect and expose errors properlyErrors lose context as they bubble up, and handlers can't tell 'not found' from a database outage.
- Write HTTP middleware for logging, recovery and request IDsEvery handler repeats logging and panics crash the request without a useful log.
- Write small generic helpers with slices and mapsThe same filter, map and group-by loops are rewritten for every type.
- Write table-driven tests with subtestsTests for a function with many cases are long, repetitive and stop at the first failure.