Go并发模型与模式:context 上下文控制
在 Go 的并发编程中,goroutine 虽然轻量高效,但也容易“失控”——一旦启动就很难精确停止。为了控制并发协程的取消、超时、信号传递和生命周期管理,Go 官方引入了
context
包。
一、为什么需要 context?
假设一个请求需同时发起多个协程处理,如果客户端中断请求,你就需要及时关闭所有协程以节省资源。这就是 context
的典型应用场景:
- • ✅ 控制 goroutine 生命周期
- • ✅ 统一管理取消信号和超时
- • ✅ 传递跨 API 层的数据
二、context 的基本使用
Go 提供四种常见 context 创建方式:
context.Background() // 最初始的上下文,常用作根 context
context.TODO() // 占位用,尚未确定如何传入 context 时使用
context.WithCancel(ctx) // 可调用 cancel() 主动取消
context.WithTimeout(ctx, d) // 指定超时时间
context.WithDeadline(ctx, t) // 指定截止时间
三、context.WithCancel 示例:主动取消
package mainimport ("context""fmt""time"
)func worker(ctx context.Context, name string) {for {select {case <-ctx.Done():fmt.Println(name, "被取消")returndefault:fmt.Println(name, "正在工作")time.Sleep(time.Second)}}
}func main() {ctx, cancel := context.WithCancel(context.Background())go worker(ctx, "worker1")go worker(ctx, "worker2")time.Sleep(3 * time.Second)cancel() // 通知所有携带该 context 的协程停止time.Sleep(1 * time.Second)
}
四、context.WithTimeout 示例:自动超时取消
func main() {ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)defer cancel()select {case <-time.After(5 * time.Second):fmt.Println("任务完成")case <-ctx.Done():fmt.Println("超时取消:", ctx.Err())}
}
五、在 channel 模式中使用 context 控制 goroutine
结合 channel 和 worker pool:
func worker(ctx context.Context, jobs <-chan int, results chan<- int) {for {select {case <-ctx.Done():returncase job, ok := <-jobs:if !ok {return}results <- job * 2}}
}
六、context 的值传递功能
context
还可以在多个函数间传递一些只读值(例如:请求 ID、用户 token 等):
ctx := context.WithValue(context.Background(), "trace_id", "abc123")
doSomething(ctx)func doSomething(ctx context.Context) {traceID := ctx.Value("trace_id")fmt.Println("Trace ID:", traceID)
}
⚠️ 不推荐用它来传递业务参数,仅用于日志追踪、认证信息等不可变值。
七、最佳实践与注意事项
建议 | 描述 |
✅ 统一根 context | 每个服务入口处使用 context.Background() 或 context.TODO() |
✅ 及时调用 cancel() | 否则 goroutine 不会释放,造成泄露 |
✅ 在 goroutine 内监听 ctx.Done() | 接收到取消信号后及时退出 |
⚠️ 避免 context.Value 滥用 | 只传递与请求作用域相关的元信息 |
八、小结
- •
context
是 Go 并发模型中重要的资源控制机制; - • 能有效解决 goroutine 泄漏、超时处理、取消信号问题;
- • 与
goroutine + channel
搭配使用,可以构建健壮的并发系统。