$npx -y skills add samber/cc-skills-golang --skill golang-contextIdiomatic context.Context usage in Golang — propagation through API boundaries, cancellation, timeouts and deadlines, request-scoped values, context.WithoutCancel for background work outliving requests. Apply when designing context propagation across layers, debugging leaked or u
| 1 | > **Community default.** A company skill that explicitly supersedes `samber/cc-skills-golang@golang-context` skill takes precedence. |
| 2 | |
| 3 | # Go context.Context Best Practices |
| 4 | |
| 5 | `context.Context` is Go's mechanism for propagating cancellation signals, deadlines, and request-scoped values across API boundaries and between goroutines. Think of it as the "session" of a request — it ties together every operation that belongs to the same unit of work. |
| 6 | |
| 7 | ## Best Practices Summary |
| 8 | |
| 9 | 1. The same context MUST be propagated through the entire request lifecycle: HTTP handler → service → DB → external APIs |
| 10 | 2. `ctx` MUST be the first parameter, named `ctx context.Context` |
| 11 | 3. NEVER store context in a struct — pass explicitly through function parameters |
| 12 | 4. NEVER pass `nil` context — use `context.TODO()` if unsure |
| 13 | 5. `cancel()` MUST be called on all control-flow paths for `WithCancel`/`WithTimeout`/`WithDeadline`, unless ownership of the context and cancel function is explicitly returned or transferred |
| 14 | 6. `context.Background()` MUST only be used at the top level (main, init, tests) |
| 15 | 7. **Use `context.TODO()`** as a placeholder when you know a context is needed but don't have one yet |
| 16 | 8. NEVER create a new `context.Background()` in the middle of a request path |
| 17 | 9. Context value keys MUST be unexported types to prevent collisions |
| 18 | 10. Context values MUST only carry request-scoped metadata — NEVER function parameters |
| 19 | 11. **Use `context.WithoutCancel`** (Go 1.21+) when spawning background work that must outlive the parent request |
| 20 | |
| 21 | ## Creating Contexts |
| 22 | |
| 23 | | Situation | Use | |
| 24 | | --- | --- | |
| 25 | | Entry point (main, init, test) | `context.Background()` | |
| 26 | | Function needs context but caller doesn't provide one yet | `context.TODO()` | |
| 27 | | Inside an HTTP handler | `r.Context()` | |
| 28 | | Need cancellation control | `context.WithCancel(parentCtx)` | |
| 29 | | Need a deadline/timeout | `context.WithTimeout(parentCtx, duration)` | |
| 30 | |
| 31 | ## Context Propagation: The Core Principle |
| 32 | |
| 33 | The most important rule: **propagate the same context through the entire call chain**. When you propagate correctly, cancelling the parent context cancels all downstream work automatically. |
| 34 | |
| 35 | ```go |
| 36 | // ✗ Bad — creates a new context, breaking the chain |
| 37 | func (s *OrderService) Create(ctx context.Context, order Order) error { |
| 38 | return s.db.ExecContext(context.Background(), "INSERT INTO orders ...", order.ID) |
| 39 | } |
| 40 | |
| 41 | // ✓ Good — propagates the caller's context |
| 42 | func (s *OrderService) Create(ctx context.Context, order Order) error { |
| 43 | return s.db.ExecContext(ctx, "INSERT INTO orders ...", order.ID) |
| 44 | } |
| 45 | ``` |
| 46 | |
| 47 | ## Deep Dives |
| 48 | |
| 49 | - **[Cancellation, Timeouts & Deadlines](./references/cancellation.md)** — How cancellation propagates: `WithCancel` for manual cancellation, `WithTimeout` for automatic cancellation after a duration, `WithDeadline` for absolute time deadlines. Patterns for listening (`<-ctx.Done()`) in concurrent code, `AfterFunc` callbacks, and `WithoutCancel` for operations that must outlive their parent request (e.g., audit logs). |
| 50 | |
| 51 | - **[Context Values & Cross-Service Tracing](./references/values-tracing.md)** — Safe context value patterns: unexported key types to prevent namespace collisions, when to use context values (request ID, user ID) vs function parameters. Trace context propagation: OpenTelemetry trace headers, correlation IDs for log aggregation, and marshaling/unmarshaling context across service boundaries. |
| 52 | |
| 53 | - **[Context in HTTP Servers & Service Calls](./references/http-services.md)** — HTTP handler context: `r.Context()` for request-scoped cancellation, middleware integration, and propagating to services. HTTP client patterns: `NewRequestWithContext`, client timeouts, and retries with context awareness. Database operations: always use `*Context` variants (`QueryContext`, `ExecContext`) to respect deadlines. |
| 54 | |
| 55 | ## Cross-References |
| 56 | |
| 57 | - → See the `samber/cc-skills-golang@golang-concurrency` skill for goroutine cancellation patterns using context |
| 58 | - → See the `samber/cc-skills-golang@golang-database` skill for context-aware database operations (QueryContext, ExecContext) |
| 59 | - → See the `samber/cc-skills-golang@golang-observ |