Working with Context
1. Creating Context with Timeout
| Function | Use |
|---|---|
WithTimeout | Relative duration |
WithDeadline | Absolute time |
WithCancel | Manual cancel |
2. Creating Context with Deadline
Example: Deadline
ctx, cancel := context.WithDeadline(parent, time.Now().Add(5*time.Second))
defer cancel()
| Use | Detail |
|---|---|
| Pipeline budget | One deadline shared across many calls |
| Wall-clock cap | Bound total operation |
3. Creating Context with Cancellation
| Pattern | Detail |
|---|---|
WithCancel | Manual control |
WithCancelCause(err) Go 1.20+ | Attach reason |
context.Cause(ctx) | Retrieve cancellation cause |
4. Propagating Context
| Rule | Detail |
|---|---|
| Always pass ctx | First argument of every function |
| Never store ctx in structs | Per-request only |
| Forward to clients | Auto-propagates deadlines, metadata, cancellation |
5. Checking Context Cancellation
6. Getting Context Error
| Error | Cause |
|---|---|
context.Canceled | Cancel called |
context.DeadlineExceeded | Timeout reached |
7. Adding Context Values
Example: Typed key
type userIDKey struct{}
ctx = context.WithValue(ctx, userIDKey{}, "u123")
id, _ := ctx.Value(userIDKey{}).(string)
| Rule | Detail |
|---|---|
| Use unexported key type | Avoid collisions |
| Only request-scoped data | Not for config, logger, etc. |
8. Using Background Context
| Context | Use |
|---|---|
context.Background() | Root of long-running processes |
context.TODO() | Placeholder during refactor |
9. Setting Default Timeout
Example: Interceptor sets default deadline
func WithDefault(timeout time.Duration) grpc.UnaryClientInterceptor {
return func(ctx context.Context, method string, req, reply any,
cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
if _, ok := ctx.Deadline(); !ok {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, timeout)
defer cancel()
}
return invoker(ctx, method, req, reply, cc, opts...)
}
}
10. Handling Context Timeout Errors
| Side | Sees |
|---|---|
| Client | codes.DeadlineExceeded |
| Server handler | ctx.Err() == context.DeadlineExceeded |
| Downstream call | Inherits remaining time minus network |