golang-context

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
Community default. A company skill that explicitly supersedes
samber/cc-skills-golang@golang-context
skill takes precedence.
社区默认规范。若存在明确替代
samber/cc-skills-golang@golang-context
的企业技能,以该企业技能为准。

Go context.Context Best Practices

Go context.Context 最佳实践

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.
context.Context
是Go语言中用于在API边界和goroutine之间传播取消信号、截止时间以及请求作用域值的机制。可以将其视为请求的“会话”,它将属于同一工作单元的所有操作关联在一起。

Best Practices Summary

最佳实践摘要

  1. The same context MUST be propagated through the entire request lifecycle: HTTP handler → service → DB → external APIs
  2. ctx
    MUST be the first parameter, named
    ctx context.Context
  3. NEVER store context in a struct — pass explicitly through function parameters
  4. NEVER pass
    nil
    context — use
    context.TODO()
    if unsure
  5. cancel()
    MUST always be deferred immediately after
    WithCancel
    /
    WithTimeout
    /
    WithDeadline
  6. context.Background()
    MUST only be used at the top level (main, init, tests)
  7. Use
    context.TODO()
    as a placeholder when you know a context is needed but don't have one yet
  8. NEVER create a new
    context.Background()
    in the middle of a request path
  9. Context value keys MUST be unexported types to prevent collisions
  10. Context values MUST only carry request-scoped metadata — NEVER function parameters
  11. Use
    context.WithoutCancel
    (Go 1.21+) when spawning background work that must outlive the parent request
  1. 必须在整个请求生命周期中传递同一个上下文:HTTP处理器 → 服务 → 数据库 → 外部API
  2. ctx
    必须作为函数的第一个参数,命名为
    ctx context.Context
  3. 绝对不要将上下文存储在结构体中——始终通过函数参数显式传递
  4. 绝对不要传递
    nil
    上下文——若不确定,使用
    context.TODO()
  5. 在调用
    WithCancel
    /
    WithTimeout
    /
    WithDeadline
    后,必须立即延迟调用
    cancel()
  6. context.Background()
    只能在顶层使用(main函数、init函数、测试中)
  7. **使用
    context.TODO()
    **作为占位符,当你知道需要上下文但尚未获取到的时候
  8. 绝对不要在请求处理路径的中间环节创建新的
    context.Background()
  9. 上下文值的键必须是未导出类型,以避免冲突
  10. 上下文值只能携带请求作用域的元数据——绝对不要用于传递函数参数
  11. 使用
    context.WithoutCancel
    (Go 1.21+),当你需要启动必须在父请求结束后继续运行的后台任务时(例如审计日志)

Creating Contexts

上下文创建场景

SituationUse
Entry point (main, init, test)
context.Background()
Function needs context but caller doesn't provide one yet
context.TODO()
Inside an HTTP handler
r.Context()
Need cancellation control
context.WithCancel(parentCtx)
Need a deadline/timeout
context.WithTimeout(parentCtx, duration)
场景使用方法
入口点(main、init、测试)
context.Background()
函数需要上下文但调用方尚未提供
context.TODO()
HTTP处理器内部
r.Context()
需要手动控制取消
context.WithCancel(parentCtx)
需要设置超时/截止时间
context.WithTimeout(parentCtx, duration)

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:
    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).
  • 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:
    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.
  • 取消、超时与截止时间 —— 取消信号的传播机制:使用
    WithCancel
    进行手动取消,
    WithTimeout
    在指定时长后自动取消,
    WithDeadline
    设置绝对时间截止。并发代码中监听
    <-ctx.Done()
    的模式、
    AfterFunc
    回调,以及使用
    WithoutCancel
    处理必须在父请求结束后继续运行的操作(如审计日志)。
  • 上下文值与跨服务追踪 —— 安全的上下文值使用模式:使用未导出的键类型避免命名空间冲突,区分何时使用上下文值(请求ID、用户ID)与函数参数。追踪上下文传播:OpenTelemetry追踪头、日志聚合的关联ID,以及跨服务边界的上下文序列化/反序列化。
  • HTTP服务器与服务调用中的上下文 —— HTTP处理器上下文:使用
    r.Context()
    实现请求作用域的取消、中间件集成以及向服务层传播。HTTP客户端模式:
    NewRequestWithContext
    、客户端超时,以及支持上下文感知的重试机制。数据库操作:始终使用带
    *Context
    后缀的方法(
    QueryContext
    ExecContext
    )以遵守截止时间。

Cross-References

交叉参考

  • → See the
    samber/cc-skills-golang@golang-concurrency
    skill for goroutine cancellation patterns using context
  • → See the
    samber/cc-skills-golang@golang-database
    skill for context-aware database operations (QueryContext, ExecContext)
  • → See the
    samber/cc-skills-golang@golang-observability
    skill for trace context propagation with OpenTelemetry
  • → See the
    samber/cc-skills-golang@golang-design-patterns
    skill for timeout and resilience patterns
  • → 查看
    samber/cc-skills-golang@golang-concurrency
    技能,了解使用上下文实现goroutine取消的模式
  • → 查看
    samber/cc-skills-golang@golang-database
    技能,了解支持上下文感知的数据库操作(QueryContext、ExecContext)
  • → 查看
    samber/cc-skills-golang@golang-observability
    技能,了解使用OpenTelemetry传播追踪上下文
  • → 查看
    samber/cc-skills-golang@golang-design-patterns
    技能,了解超时与弹性模式

Enforce with Linters

使用代码检查工具强制执行

Many context pitfalls are caught automatically by linters:
govet
,
staticcheck
. → See the
samber/cc-skills-golang@golang-linter
skill for configuration and usage.
许多上下文使用陷阱可以通过代码检查工具自动捕获:
govet
staticcheck
。→ 查看
samber/cc-skills-golang@golang-linter
技能了解配置和使用方法。