在 Go 语言中,context
包是一个非常重要的工具,主要用于 跨 API 边界传递请求相关的数据、控制超时和取消协程。它的核心应用场景包括:
1. 请求超时控制
当某个操作(如 HTTP 请求、数据库查询等)耗时过长时,可以通过 context.WithTimeout
或 context.WithDeadline
设置超时,避免资源阻塞。
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
// 将 ctx 传递给可能耗时的函数
result, err := someLongRunningOperation(ctx)
if errors.Is(err, context.DeadlineExceeded) {
log.Println("操作超时")
}
2. 协程的取消与传播
通过 context.WithCancel
创建可取消的上下文,通知所有派生协程退出(例如用户中断请求或服务关闭时)。
ctx, cancel := context.WithCancel(context.Background())
go func() {
time.Sleep(2 * time.Second)
cancel() // 手动触发取消
}()
select {
case <-ctx.Done():
log.Println("协程被取消:", ctx.Err()) // context.Canceled
}
3. 跨服务传递数据
使用 context.WithValue
安全地传递请求范围的元数据(如 TraceID、认证信息),避免全局变量污染。
type key string
const requestIDKey key = "request_id"
// 存储值到上下文
ctx := context.WithValue(context.Background(), requestIDKey, "12345")
// 从上下文读取值
if id, ok := ctx.Value(requestIDKey).(string); ok {
log.Println("Request ID:", id) // Output: Request ID: 12345
}
4. RPC/HTTP API 链式调用
在微服务架构中,context
可以贯穿整个调用链,确保超时、取消信号和数据(如链路追踪 ID)在服务间透传。
// HTTP Server -> RPC Client -> Database Call
func handler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context() // 继承请求的上下文
// RPC调用(自动传递超时和取消)
resp, err := grpcClient.Call(ctx, request)
if err != nil {
handleError(w, err)
return
}
}
5. Serverless/Cloud Native
在 Kubernetes、Serverless Function(如 AWS Lambda)等场景中,context
用于接收平台的中断信号(如 Pod Terminate),实现优雅退出。
关键注意事项
- 不要滥用 WithValue:仅传递必要的请求范围数据,而非函数参数。
- 始终检查 Done():避免因未处理取消信号导致协程泄漏。
- 线程安全:Context是并发安全的,但 Value中的数据类型需自行保证安全。
如果需要更具体的代码示例或场景解释,可以进一步说明!
内容由零声教学AI助手提供,问题来源于学员提问