Go: 标准库 context
Outlinks (0)
No outlinks found
Backlinks (1)
Backlinks (1)
1 · 标准库 context#
context 包定义了一个上下文Context类型;
这个类型在跨越 API 边界和进程之间,携带了超时,取消信号,以及其他请求域内的值;
在不同执行任务(比如 goroutine)之间传递Context值,可以实现超时,取消功能,也可以实现跨越函数的参数传递;
context 是接受信号的一方,是子操作;
派生树模型,在父ctx上派生出子ctx;
本质:一条调用链/传播链上各个节点共享一套:是否超时、是否取消、值的机制。
1.1 · Context 接口#
type Context interface {
// 返回截止时间,ok 为 false 表示没有设置 deadline
// ! 未来什么时候结束,还未结束
Deadline() (deadline time.Time, ok bool)
// 返回一个 channel,当 context 被取消或超时时关闭;永远不会取消的 context 返回 nil
// ! 已经结束
Done() <-chan struct{}
// Done 未关闭返回 nil;已关闭返回原因(Canceled 或 DeadlineExceeded)
Err() error
// 返回 key 关联的值,不存在返回 nil
Value(key any) any
}
1.2 · 根 Context#
context.Background()— 通常用于 main、init 或顶层请求入口context.TODO()— 不确定用哪个 Context 时的占位符
1.3 · 派生函数
1.3.1 · 基础派生函数
| 函数 | 作用 |
|---|---|
WithCancel(parent) | 返回可手动取消的子 context 和 cancel 函数 |
WithDeadline(parent, d) | 到达时间点 d 自动取消 |
WithTimeout(parent, t) | 经过时长 t 自动取消(等价于 WithDeadline(parent, time.Now().Add(t))) |
WithValue(parent, key, val) | 附带一个 key-value 对,用于请求域数据的传递 |
WithoutCancel(parent) 返回一个不会随父 context 取消而取消的派生 context
AfterFunc(ctx, f) ctx 取消后,在新 goroutine 中执行 f(Go 1.21)
1.3.2 · 带 Cause 的取消 API#
| 函数 | 作用 |
|---|---|
WithCancelCause(parent) | 在普通取消基础上额外记录一个自定义 error 原因(Go 1.20+) |
WithDeadlineCause(parent, d, cause) | 在 deadline 取消基础上额外记录一个自定义 error 原因 |
WithTimeoutCause(parent, t, cause) | 在 timeout 取消基础上额外记录一个自定义 error 原因 |
Cause(ctx) | 读取 context 被取消的具体原因;若未显式指定 cause,则返回值通常与 ctx.Err() 一致 |
当一个 Context 被取消时,所有从它派生的子 Context 也会被取消。
1.4 · 使用规则
- 不要把 Context 存在 struct 里,显式作为函数第一个参数传递,通常命名
ctx - 不要传 nil Context,不确定时用
context.TODO() - Value 只用于请求域数据(如 trace ID、认证信息),不要用来传可选参数
- Context 是并发安全的,多个 goroutine 可同时使用
cancel函数调用后要尽快执行(通常defer cancel()),避免资源泄漏
1.5 · 错误值
调用 Err() 返回
context.Canceled— 手动调用 cancel 函数时context.DeadlineExceeded— deadline/timeout 到期时
1.6 · Go 中 context.Value 应该放什么#
如果你的代码“没有这个值就无法运行”,那这个值就不应该放进 context。 context 是“附带信息的通道”,不是“参数传递的替代品”
1.7 · cancellation cause#
谁先 cancel,谁定义原因cause
NOTE: 为什么 WithTimeoutCause 不返回 CancelCauseFunc:手动 cancel → 原因变成 context.Canceled