用context控制超时的核心是创建带截止时间的context并传递给协程或HTTP客户端;它提供统一取消信号而非强制终止协程;需用WithTimeout/WithDeadline创建,defer cancel()防泄漏;HTTP请求中通过req.WithContext(ctx)或client.Do生效;协程需在select中监听ctx.Done()协作退出。
用 context 控制超时,核心是创建带截止时间的 context,并在协程或 HTTP 客户端中传递它。Go 的 context 不是为“取消协程”而设计的,而是为“通知下游操作该停止了”提供统一信号机制。
用 context.WithTimeout 或 context.WithDeadline 生成可取消、有时限的 context:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) —— 从现在起 5 秒后自动触发 canceldefer cancel() 必须调用,否则可能泄漏 timer 和 goroutinectx 可安全传给多个函数或 goroutine,它们共用同一个取消信号标准 http.Client 支持传入 context,请求会在 context 超时或取消时立即终止(包
括 DNS、连接、TLS、读写全过程):
client.Do(req.WithContext(ctx)),无需额外封装client.Timeout 作为兜底,但优先以 context 超时为准(context 更精细、可组合)http.Request,务必调用 req.WithContext(ctx),原 req 是不可变的协程不能被强制杀死,只能协作式退出。关键是在关键阻塞点检查 ctx.Done():
select { case 替代纯 time.Sleep
db.QueryContext、ch := make(chan T, 1); select { case ch )
if ctx.Err() != nil { return },避免长时间不响应取消context 应作为第一个参数显式传入,且不要保存到结构体长期持有(除非明确是 request-scoped 的 handler):
func(ctx context.Context, ...) 开头,由上层注入context.Background() 用于主函数或测试;context.TODO() 仅当暂时不确定用哪种 context 时占位不复杂但容易忽略:超时不是加个 context 就生效,关键在所有参与环节都主动监听和响应 Done 通道。