mcpField
G
go-context

go-context

github.com/cxuu开发1861.2k 次安装19 周前更新
代码仓库

关于 go-context

go-context 汇总 Go 中使用 context 的 API 约定与常见模式,面向需要处理请求上下文、取消和超时的开发者。它强调显式传递 context.Context,并限制上下文值的适用范围。

主要功能

  1. 01将 context 作为函数首个参数
  2. 02避免在结构体中存储 Context
  3. 03规范派生上下文与取消清理
  4. 04说明上下文值的适用场景

适用场景

  1. 01设计接受请求上下文的函数
  2. 02实现超时与取消处理
  3. 03决定请求数据是否适合放入上下文值

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/cxuu/golang-skills --skill go-context

安装后在 Claude Code 中输入/go-context确认已加载。

附带文件references/PATTERNS.md

详细介绍

Go 上下文用法

兼容性:context 自 Go 1.7 起纳入标准库。

资源路由

  • references/PATTERNS.md - 在派生上下文、检查取消状态、处理 HTTP 请求上下文或使用带类型的上下文值键时阅读。

将 Context 作为第一个参数

使用 Context 的函数应将其作为第一个参数:

func F(ctx context.Context, /* other arguments */) error
func ProcessRequest(ctx context.Context, req *Request) (*Response, error)

这是 Go 中一项重要约定,可让上下文在各个代码库中的传递清晰且一致。


不要在结构体中存储 Context

不要在结构体类型中添加 Context 成员。对于需要 Context 的每个方法,应将 ctx 作为参数传入:

// Bad: Context stored in struct
type Worker struct {
    ctx context.Context  // Don't do this
}

// Good: Context passed to methods
type Worker struct{ /* ... */ }

func (w *Worker) Process(ctx context.Context) error {
    // Context explicitly passed — lifetime clear
}

例外:如果方法签名必须与标准库或第三方库中的接口匹配,可能需要采用变通方案。


不要创建自定义 Context 类型

不要创建自定义 Context 类型,也不要在函数签名中使用 context.Context 以外的接口:

// Bad: Custom context type
type MyContext interface {
    context.Context
    GetUserID() string
}

// Good: Use standard context.Context with value extraction
func Process(ctx context.Context) error {
    userID := GetUserID(ctx)
}

应将应用数据放在哪里

按以下优先顺序考虑这些选项:

  1. 函数参数 — 最明确且类型安全
  2. 接收者 — 用于属于该类型的数据
  3. 全局变量 — 用于真正的全局配置(谨慎使用)
  4. Context 值 — 仅用于请求范围内的数据

Context 值适用于:

  • 请求 ID 和跟踪 ID
  • 随请求传递的身份验证/授权信息
  • 截止时间和取消信号

Context 值不适用于:

  • 可选函数参数
  • 可显式传递的数据
  • 不随请求变化的配置

常见模式

派生上下文

创建派生上下文后,始终立即执行 defer cancel():

ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
检查取消状态
select {
case <-ctx.Done():
    return ctx.Err()
default:
    // Do work
}
Context 不可变性

Context 是不可变的——将同一个 ctx 传给多个并发调用是安全的,前提是这些调用共享相同的截止时间和取消信号。


相关技能

  • Goroutine 协调:使用 context 取消 goroutine、基于 select 的超时或 errgroup 时,请参阅 go-concurrency
  • 错误处理:决定如何包装或返回 ctx.Err() 取消错误时,请参阅 go-error-handling
  • 接口设计:设计同时接受 context 和接口的 API 时,请参阅 go-interfaces
  • 请求范围内的日志记录:将日志记录器注入 context 或将请求 ID 添加到结构化日志输出时,请参阅 go-logging

评论

支持 Markdown