Context values
Use context values only for request-scoped metadata that must cross API boundaries, not as a bag of optional parameters.
Canonical guidance
- use context values for metadata that must cross API boundaries
- keep keys typed and package-local
- pass real business inputs as explicit parameters
Use when
- request IDs
- auth or tracing metadata
- APIs that already accept context and need request-scoped values
Avoid
- storing configs or dependencies in context
- using strings as public key types
- hiding optional parameters in context because the function signature is inconvenient
Preferred pattern
type requestIDKey struct{}
func WithRequestID(ctx context.Context, id string) context.Context {
return context.WithValue(ctx, requestIDKey{}, id)
}
Anti-pattern
- using
context.WithValueto smuggle feature flags, database handles, or logger dependencies through the call graph
Explanation: This anti-pattern is tempting because it avoids changing signatures, but it destroys API clarity and type safety.
Why
- context values work best for narrow cross-cutting metadata, not for ordinary program state
Related pages
Sources
- Go Concurrency Patterns: Context - Sameer Ajmani