patterngoMajor
Context cancellation propagation: always pass ctx to downstream calls
Viewed 0 times
context cancellationcontext propagationctx deadlineHTTP request canceldatabase contextcontext.WithTimeout
Error Messages
Problem
When an HTTP request is cancelled by the client, downstream goroutines and I/O calls continue running and consuming resources unless context is explicitly threaded through.
Solution
Accept and forward ctx to every blocking call:
func handler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
result, err := fetchFromDB(ctx, userID)
if err != nil {
if errors.Is(err, context.Canceled) {
return // client disconnected
}
http.Error(w, err.Error(), 500)
return
}
json.NewEncoder(w).Encode(result)
}
func fetchFromDB(ctx context.Context, id int) (*Record, error) {
row := db.QueryRowContext(ctx, "SELECT * FROM records WHERE id=$1", id)
// query is cancelled automatically when ctx is cancelled
...
}Why
context.Context carries a cancellation signal and deadline. Stdlib APIs (database/sql, net/http, os/exec) accept ctx and stop work when it fires. Goroutines that ignore ctx waste resources after the caller no longer cares about the result.
Gotchas
- Never store a context in a struct — pass it as the first argument to every function
- context.Background() is only for top-level main/init; use r.Context() in HTTP handlers
- context.WithTimeout creates a child context; always defer the cancel function to avoid a context leak: defer cancel()
Revisions (0)
No revisions yet.