关于 go-context
go-context 汇总 Go 中使用 context 的 API 约定与常见模式,面向需要处理请求上下文、取消和超时的开发者。它强调显式传递 context.Context,并限制上下文值的适用范围。
主要功能
- 01将 context 作为函数首个参数
- 02避免在结构体中存储 Context
- 03规范派生上下文与取消清理
- 04说明上下文值的适用场景
适用场景
- 01设计接受请求上下文的函数
- 02实现超时与取消处理
- 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)
}
应将应用数据放在哪里
按以下优先顺序考虑这些选项:
- 函数参数 — 最明确且类型安全
- 接收者 — 用于属于该类型的数据
- 全局变量 — 用于真正的全局配置(谨慎使用)
- 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