Go context 包深度解析:告别 goroutine 泄漏的正确姿势
在 Go 并发编程中,goroutine 泄漏是最隐蔽也最致命的 bug 之一。今天我们来深入理解 context 包,掌握正确管理 goroutine 生命周期的方法。
为什么需要 context?
想象一个场景:一个 HTTP 请求触发了 3 个并发 goroutine 去查询数据库、调用外部 API 和写入缓存。如果客户端中途断开连接,这 3 个 goroutine 会继续执行直到完成——白白浪费资源。
正确使用 context
用 context 控制生命周期,通过 ctx.Done() 来通知子 goroutine 退出。
context 的四种类型
1. context.Background() — 根 context,永远不会被取消
2. context.TODO() — 不确定用什么时的占位符
3. context.WithCancel() — 手动取消
4. context.WithTimeout()/WithDeadline() — 超时自动取消
实战:多级超时控制
在 handleRequest 中设置总超时 10 秒,子任务分别设置 3 秒和 5 秒的超时。
关键规则
- 将 context 作为第一个参数传递
- 不要将 context 存储在结构体中
- 每一层都要检查 ctx.Done()
- 不要传入 nil 作为 context
总结
context 不是可选项,而是 Go 并发编程的必选项。它能帮你:防止 goroutine 泄漏、实现优雅超时、传递请求级元数据、级联取消节省资源。记住:每个 goroutine 都应该知道什么时候该停下来。