The Context Package
Thecontext package is essential for production Go. It provides a standardized way to carry deadlines, cancellation signals, and request-scoped values across API boundaries and between goroutines.
Why Context?
In real-world applications, you need to:- Cancel operations when a client disconnects
- Set timeouts for database queries, HTTP requests
- Pass request-scoped data like request IDs, user info
- Propagate cancellation through a chain of function calls
Context Basics
The Context Interface
Creating Contexts
Cancellation
context.WithCancel
Cancellation Propagation
Child contexts are cancelled when their parent is cancelled:Timeouts and Deadlines
context.WithTimeout
context.WithDeadline
Checking Deadline
Context Values
Storing and Retrieving Values
Type-Safe Context Values
Context in HTTP Servers
Request Context
Everyhttp.Request carries a context:
Adding Request Timeout
Context in Database Operations
With sql.DB
Transaction with Context
Context Best Practices
DO’s
DON’Ts
Context Cause (Go 1.20+)
Go 1.20 introducedcontext.WithCancelCause for better error context:
AfterFunc (Go 1.21+)
Go 1.21 addedcontext.AfterFunc to schedule cleanup:
Real-World Example: HTTP Service
Interview Questions
What happens if you don't call cancel() after WithTimeout/WithCancel?
What happens if you don't call cancel() after WithTimeout/WithCancel?
Resources are leaked! The goroutine managing the context’s timer continues running until the parent context is cancelled. Always defer
cancel() immediately after creating a cancellable context.Can context values be modified after being set?
Can context values be modified after being set?
No, contexts are immutable.
WithValue returns a new context with the added value. The original context is unchanged.What's the difference between context.Background() and context.TODO()?
What's the difference between context.Background() and context.TODO()?
Functionally identical, but semantically different:
Background(): Use at the top of the call chain (main, init, tests)TODO(): Temporary placeholder when you’re not sure which context to use
Should you store Context in a struct field?
Should you store Context in a struct field?
Generally no. Context should flow through your program via function parameters. Storing in structs can lead to stale contexts and unclear lifecycle management.
How does context cancellation propagate?
How does context cancellation propagate?
When a parent context is cancelled, all child contexts are also cancelled. The cancellation is detected by receiving from
ctx.Done(). Child context cancellation doesn’t affect the parent.Summary
| Function | Purpose |
|---|---|
context.Background() | Root context for main, init, tests |
context.TODO() | Placeholder when unsure |
context.WithCancel() | Manual cancellation |
context.WithTimeout() | Cancel after duration |
context.WithDeadline() | Cancel at specific time |
context.WithValue() | Attach request-scoped data |
context.WithCancelCause() | Cancellation with reason (Go 1.20+) |
context.AfterFunc() | Schedule cleanup (Go 1.21+) |