context.withtimeout仅发送取消信号,下游不监听ctx.done()则超时无效;需确保http用withcontext、db用querycontext、goroutine中select监听done,且cancel()覆盖所有退出路径。

context.WithTimeout 不是“设了就生效”,它只发信号,下游不听就等于没设。
为什么 ctx.Err() == context.DeadlineExceeded 却没中断请求
超时后 ctx.Err() 返回 context.DeadlineExceeded,但请求仍在跑,说明下游函数根本没检查这个信号。
- HTTP 请求没用
http.NewRequestWithContext(ctx, ...)构造请求,或调用client.Do(req)时传的是原始req而非req.WithContext(ctx) - 数据库查询用了
db.Query(...)而非db.QueryContext(ctx, ...) - 自定义 goroutine 里有
time.Sleep、for range ch或阻塞 I/O,但没在select中监听ctx.Done() - 第三方库不支持 context(比如老版本
redis-go或裸net.Conn),需手动加conn.SetReadDeadline()等原生控制
WithTimeout 和 WithDeadline 到底该选哪个
95% 的场景用 context.WithTimeout 就够了,它语义明确、抗时钟漂移、无需手动算时间点。
-
context.WithTimeout(parentCtx, 3*time.Second):从调用那一刻起计时,底层用单调时钟,休眠/ntp 调整不影响 -
context.WithDeadline(parentCtx, time.Now().Add(3*time.Second)):传的是绝对时间,若系统时间被回拨,可能提前触发;若机器休眠再唤醒,deadline 已过,ctx 立即取消 - 别写
context.WithDeadline(ctx, time.Now().Add(d))—— 这和WithTimeout行为一致,还多一层计算,容易出错 - 真正需要
WithDeadline的场景极少:比如分布式任务必须对齐外部调度器的截止时间(如 Airflow 的execution_date + timeout)
cancel() 忘调或 defer 失效的典型漏点
不调 cancel() 不会卡住 goroutine,但会泄漏 timer 和内部 channel,高频服务几天下来内存明显上涨。
- 函数有多个
return分支,只在末尾defer cancel(),但中间if err != nil { return }就跳出了,cancel()永远不执行 - panic 后未 recover,
defer不触发,必须在关键路径上显式调用cancel() - HTTP handler 中:在
recover()捕获 panic 后、return前漏掉cancel() - select 的
default分支里做了快速返回,也忘了调cancel() - 别在一个函数里多次
defer cancel()—— 第二次调用静默失败,但你误以为“已释放”
超时起点不是 IO 发起时刻,而是 WithTimeout 调用时刻
这是最常被误判的一点:超时倒计时从 context.WithTimeout 执行那行代码开始,不是从 http.Do 或 db.QueryContext 开始。
- 主线程在锁里卡了 1.8 秒,再调
context.WithTimeout(ctx, 2*time.Second),实际只剩 200ms 可用 - 如果想“真正从网络请求发出那一刻计时”,必须把
WithTimeout放在构造请求前,而不是 handler 入口就创建 - 链路中嵌套多个
WithTimeout(比如网关 5s → 服务 A 2s → DB 800ms),外层超时包含内层创建开销,总耗时不等于各层简单相加 - 测试时用
time.Sleep模拟耗时,因调度器抢占延迟,timer 实际触发可能比预期晚几十毫秒,别拿它做精确验证
真正难的不是写对那一行 ctx, cancel := context.WithTimeout(...),而是确保整个调用链——从 handler 入口、到每个 http client、每个 db query、每个自定义 goroutine —— 都主动监听 ctx.Done(),且所有 cancel() 调用点都覆盖了 panic、error return、正常退出这三种路径。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











