patterngoMajorpending
Go Context for Cancellation, Timeouts, and Values
Viewed 0 times
contextcancellationtimeoutWithTimeoutWithCancelWithValuegoroutine
Problem
Go applications need to propagate cancellation signals, enforce timeouts, and pass request-scoped values across API boundaries and goroutines.
Solution
Context patterns in Go:
Rules:
import (
"context"
"fmt"
"time"
)
// Timeout context
func fetchWithTimeout(url string) ([]byte, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel() // ALWAYS defer cancel to release resources
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err // Returns context.DeadlineExceeded on timeout
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}
// Cancellation propagation
func processItems(ctx context.Context, items []Item) error {
for _, item := range items {
select {
case <-ctx.Done():
return ctx.Err() // context.Canceled or DeadlineExceeded
default:
if err := process(ctx, item); err != nil {
return err
}
}
}
return nil
}
// HTTP handler with context
func handler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context() // Cancelled when client disconnects
result, err := fetchData(ctx)
if err != nil {
if ctx.Err() != nil {
return // Client disconnected, don't write response
}
http.Error(w, err.Error(), 500)
return
}
json.NewEncoder(w).Encode(result)
}
// Context values (use sparingly)
type contextKey string
const requestIDKey contextKey = "requestID"
func WithRequestID(ctx context.Context, id string) context.Context {
return context.WithValue(ctx, requestIDKey, id)
}
func RequestID(ctx context.Context) string {
id, _ := ctx.Value(requestIDKey).(string)
return id
}Rules:
- Context is the first parameter:
func Foo(ctx context.Context, ...) - ALWAYS call cancel (defer cancel())
- Don't store context in structs
- Use context values only for request-scoped data (trace ID, auth), not function parameters
Why
Context provides a standard way to signal cancellation across goroutines. Without it, goroutines leak when their parent operation is cancelled or times out.
Gotchas
- context.Background() has no deadline or cancellation - use as root only
- Context values use interface{} keys - use unexported types to avoid collisions
Context
Managing cancellation and timeouts in Go
Revisions (0)
No revisions yet.