Summary of Go Context Usage Specifications: Key Points for Timeout Propagation and Cancellation Signal Handling

Our team enforces three hard rules for code reviews:
First, `ctx` is always the first parameter and must not be stored as a struct field. Storing request-scoped values inside long-lived objects breaks cancellation signals. Use `WithCancelCause` in Go 1.21+ to carry cancellation reasons; on-call engineers will appreciate this during troubleshooting.
Second, whoever calls `WithTimeout` must `defer cancel`. Call `cancel` even on normal function return. Otherwise, timers leak and are only released upon timeout. Enable `containedctx` and `govet` in golangci-lint to catch most such issues.
Third, any spawned goroutine must listen to `ctx.Done()` before exiting. This is critical for goroutines inside loops that skip context checks — they may keep writing to the database long after the request has timed out.
Additionally, use custom keys (private struct types) for passing trace information across functions. Do not reuse built-in context keys to transmit business parameters; this is explicitly warned against in the design documentation.
Do not compute minimum timeouts at every layer for timeout propagation. Set an overall budget at the entrypoint, and configure separate child timeouts for downstream `http.Client` and database calls.

Leave a Comment