What is the context package used for and how do you use it correctly?
context.Context carries deadlines, cancellation signals and request-scoped values across API boundaries and goroutines. It is how cancellation and timeouts propagate through a call tree.
func handler(ctx context.Context) error {
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
_, err := http.DefaultClient.Do(req)
return err
}
Key rules:
- Cancellation propagates down the tree: cancelling a parent cancels every derived context.
- Always call the cancel function, usually with
defer, to release timers and resources. - Pass
ctxas the first parameter and checkctx.Done()in loops and blocking selects. - Use
WithValuesparingly, only for request-scoped metadata such as trace IDs, never for optional parameters. - Never store a Context inside a struct; pass it explicitly through calls.
Common bugs are ignoring cancellation so work continues after a client disconnects, and misusing values as a hidden dependency injection channel.