golang-context
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCommunity default. A company skill that explicitly supersedesskill takes precedence.samber/cc-skills-golang@golang-context
社区默认规范。若存在明确替代的企业技能,以该企业技能为准。samber/cc-skills-golang@golang-context
Go context.Context Best Practices
Go context.Context 最佳实践
context.Contextcontext.ContextBest Practices Summary
最佳实践摘要
- The same context MUST be propagated through the entire request lifecycle: HTTP handler → service → DB → external APIs
- MUST be the first parameter, named
ctxctx context.Context - NEVER store context in a struct — pass explicitly through function parameters
- NEVER pass context — use
nilif unsurecontext.TODO() - MUST always be deferred immediately after
cancel()/WithCancel/WithTimeoutWithDeadline - MUST only be used at the top level (main, init, tests)
context.Background() - Use as a placeholder when you know a context is needed but don't have one yet
context.TODO() - NEVER create a new in the middle of a request path
context.Background() - Context value keys MUST be unexported types to prevent collisions
- Context values MUST only carry request-scoped metadata — NEVER function parameters
- Use (Go 1.21+) when spawning background work that must outlive the parent request
context.WithoutCancel
- 必须在整个请求生命周期中传递同一个上下文:HTTP处理器 → 服务 → 数据库 → 外部API
- 必须作为函数的第一个参数,命名为
ctxctx context.Context - 绝对不要将上下文存储在结构体中——始终通过函数参数显式传递
- 绝对不要传递上下文——若不确定,使用
nilcontext.TODO() - 在调用/
WithCancel/WithTimeout后,必须立即延迟调用WithDeadlinecancel() - 只能在顶层使用(main函数、init函数、测试中)
context.Background() - **使用**作为占位符,当你知道需要上下文但尚未获取到的时候
context.TODO() - 绝对不要在请求处理路径的中间环节创建新的
context.Background() - 上下文值的键必须是未导出类型,以避免冲突
- 上下文值只能携带请求作用域的元数据——绝对不要用于传递函数参数
- 使用(Go 1.21+),当你需要启动必须在父请求结束后继续运行的后台任务时(例如审计日志)
context.WithoutCancel
Creating Contexts
上下文创建场景
| Situation | Use |
|---|---|
| Entry point (main, init, test) | |
| Function needs context but caller doesn't provide one yet | |
| Inside an HTTP handler | |
| Need cancellation control | |
| Need a deadline/timeout | |
| 场景 | 使用方法 |
|---|---|
| 入口点(main、init、测试) | |
| 函数需要上下文但调用方尚未提供 | |
| HTTP处理器内部 | |
| 需要手动控制取消 | |
| 需要设置超时/截止时间 | |
Context Propagation: The Core Principle
上下文传播:核心原则
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.
go
// ✗ Bad — creates a new context, breaking the chain
func (s *OrderService) Create(ctx context.Context, order Order) error {
return s.db.ExecContext(context.Background(), "INSERT INTO orders ...", order.ID)
}
// ✓ Good — propagates the caller's context
func (s *OrderService) Create(ctx context.Context, order Order) error {
return s.db.ExecContext(ctx, "INSERT INTO orders ...", order.ID)
}最重要的规则:在整个调用链中传递同一个上下文。当你正确传播上下文时,取消父上下文会自动取消所有下游的工作。
go
// ✗ 错误示例——创建新上下文,打断调用链
func (s *OrderService) Create(ctx context.Context, order Order) error {
return s.db.ExecContext(context.Background(), "INSERT INTO orders ...", order.ID)
}
// ✓ 正确示例——传递调用者的上下文
func (s *OrderService) Create(ctx context.Context, order Order) error {
return s.db.ExecContext(ctx, "INSERT INTO orders ...", order.ID)
}Deep Dives
深度解析
-
Cancellation, Timeouts & Deadlines — How cancellation propagates:for manual cancellation,
WithCancelfor automatic cancellation after a duration,WithTimeoutfor absolute time deadlines. Patterns for listening (WithDeadline) in concurrent code,<-ctx.Done()callbacks, andAfterFuncfor operations that must outlive their parent request (e.g., audit logs).WithoutCancel -
Context Values & Cross-Service Tracing — 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.
-
Context in HTTP Servers & Service Calls — HTTP handler context:for request-scoped cancellation, middleware integration, and propagating to services. HTTP client patterns:
r.Context(), client timeouts, and retries with context awareness. Database operations: always useNewRequestWithContextvariants (*Context,QueryContext) to respect deadlines.ExecContext
-
取消、超时与截止时间 —— 取消信号的传播机制:使用进行手动取消,
WithCancel在指定时长后自动取消,WithTimeout设置绝对时间截止。并发代码中监听WithDeadline的模式、<-ctx.Done()回调,以及使用AfterFunc处理必须在父请求结束后继续运行的操作(如审计日志)。WithoutCancel -
上下文值与跨服务追踪 —— 安全的上下文值使用模式:使用未导出的键类型避免命名空间冲突,区分何时使用上下文值(请求ID、用户ID)与函数参数。追踪上下文传播:OpenTelemetry追踪头、日志聚合的关联ID,以及跨服务边界的上下文序列化/反序列化。
-
HTTP服务器与服务调用中的上下文 —— HTTP处理器上下文:使用实现请求作用域的取消、中间件集成以及向服务层传播。HTTP客户端模式:
r.Context()、客户端超时,以及支持上下文感知的重试机制。数据库操作:始终使用带NewRequestWithContext后缀的方法(*Context、QueryContext)以遵守截止时间。ExecContext
Cross-References
交叉参考
- → See the skill for goroutine cancellation patterns using context
samber/cc-skills-golang@golang-concurrency - → See the skill for context-aware database operations (QueryContext, ExecContext)
samber/cc-skills-golang@golang-database - → See the skill for trace context propagation with OpenTelemetry
samber/cc-skills-golang@golang-observability - → See the skill for timeout and resilience patterns
samber/cc-skills-golang@golang-design-patterns
- → 查看技能,了解使用上下文实现goroutine取消的模式
samber/cc-skills-golang@golang-concurrency - → 查看技能,了解支持上下文感知的数据库操作(QueryContext、ExecContext)
samber/cc-skills-golang@golang-database - → 查看技能,了解使用OpenTelemetry传播追踪上下文
samber/cc-skills-golang@golang-observability - → 查看技能,了解超时与弹性模式
samber/cc-skills-golang@golang-design-patterns
Enforce with Linters
使用代码检查工具强制执行
Many context pitfalls are caught automatically by linters: , . → See the skill for configuration and usage.
govetstaticchecksamber/cc-skills-golang@golang-linter许多上下文使用陷阱可以通过代码检查工具自动捕获:、。→ 查看技能了解配置和使用方法。
govetstaticchecksamber/cc-skills-golang@golang-linter