Go并发Context
深入理解 Go Context:从原理到最佳实践
EasyGo2025-11-2512 分钟
什么是 Context?
Context(上下文)是 Go 1.7 引入的标准库,用于在 goroutine 之间传递截止时间、取消信号和请求范围的值。
Context 的核心接口
go
1type Context interface {2 Deadline() (deadline time.Time, ok bool)3 Done() <-chan struct{}4 Err() error5 Value(key any) any6}Deadline
返回 context 被取消的时间,如果没有设置截止时间,ok 返回 false。
Done
返回一个 channel,当 context 被取消或超时时,该 channel 会被关闭。
Err
返回 context 取消的原因:
Value
用于从 context 中获取键值对,常用于传递请求级别的数据。
创建 Context
Background 和 TODO
go
1ctx := context.Background() // 根 context2ctx := context.TODO() // 占位符WithCancel
go
1ctx, cancel := context.WithCancel(context.Background())2defer cancel() // 确保资源释放WithTimeout 和 WithDeadline
go
1// 超时控制2ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)3defer cancel()45// 设置截止时间6ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(5*time.Second))7defer cancel()最佳实践
2. **不要存储 Context**
3. **使用 WithCancel/WithTimeout 控制 goroutine 生命周期**
4. **不要传递 nil Context**
5. **Context 的 Value 只用于传递请求范围的数据**
实战示例
go
1func fetchData(ctx context.Context, url string) ([]byte, error) {2 req, err := http.NewRequestWithContext(ctx, "GET", url, nil)3 if err != nil {4 return nil, err5 }6 7 resp, err := http.DefaultClient.Do(req)8 if err != nil {9 return nil, err10 }11 defer resp.Body.Close()12 13 return io.ReadAll(resp.Body)14}总结
Context 是 Go 并发编程的核心工具,正确使用 Context 可以优雅地处理请求取消、超时控制和数据传递。