gin 默认 handler 不响应 cancel 信号,因其仅提供 c.request.context() 起点,未在业务逻辑中显式监听 ctx.done();若子 goroutine 未传入 context 或未检查 done(),将导致 shutdown() 无法等待其结束,进程卡住、连接不释放、事务中断。

router.Run() 不处理上下文取消信号,必须手动把 context.Context 传进 handler 并监听 ctx.Done(),否则 goroutine 会一直跑、连接不释放、Shutdown() 等不到它结束。
为什么 Gin 的默认 handler 不响应 cancel 信号
Gin 的 c.Request.Context() 是从 HTTP 连接创建的,但它只是个“起点”——你没在业务逻辑里显式监听 ctx.Done(),那它就只是个摆设。比如你在 handler 里起个 go sendToKafka(c),又没传 context 或 select 判断 c.Request.Context().Done(),这个 goroutine 就完全不受 Shutdown 控制,进程卡住是常态。
常见错误现象:curl -N http://localhost:8080/stream 后 Ctrl+C,服务日志显示 “Server closed”,但进程 ps 还在;或者数据库事务没提交、文件上传只写了一半就没了。
- 别依赖 Gin 自动传播 cancel:它不自动中断你的子 goroutine
- 所有阻塞操作(
time.Sleep、db.QueryRow、redis.Do、http.Post)都得用带 context 的变体,如db.QueryRowContext(c.Request.Context(), ...) - 自己启的 goroutine 必须用
select { case 做退出守门员
如何在 Gin handler 中正确使用 context 取消
核心不是“加 context”,而是“让每个可能阻塞的点都可中断”。Gin 的 c.Request.Context() 已经绑定了请求生命周期,直接复用即可,不用另建新 context。
示例对比:
// ❌ 错误:没监听取消,goroutine 永不退出
func badHandler(c *gin.Context) {
go func() {
time.Sleep(10 * time.Second) // 卡死,Shutdown 等不到它
log.Println("done")
}()
c.String(200, "ok")
}
<p>// ✅ 正确:用 handler 的 context 控制子 goroutine
func goodHandler(c <em>gin.Context) {
ctx := c.Request.Context()
go func() {
select {
case time.Second):
log.Println("done")
case </em></p>
- HTTP 流式响应(SSE、chunked)必须在每次 write 前检查
ctx.Err() != nil - 长轮询或 WebSocket 升级后,要换用
c.Copy() + c.Request.Context()继续传递 - 不要在 handler 里调
context.WithCancel(c.Request.Context())再传给子 goroutine——除非你真需要独立取消分支
哪些地方最容易漏掉 context 取消监听
不是所有“看起来会卡住”的地方都显眼。以下三类是高频泄漏点:
-
time.AfterFunc(5*time.Second, ...):它不认 context,应改用time.NewTimer+select监听ctx.Done() - 第三方 SDK 调用(如 Kafka producer、Elasticsearch client):查文档确认有没有
WithContext()方法,没有就 wrap 一层带超时的context.WithTimeout(ctx, ...) - 数据库连接池本身不阻塞,但
db.Query不带 context 会忽略 cancel;务必用db.QueryContext(ctx, ...)或tx.QueryRowContext(...)
验证方法很简单:启动服务后发一个 5 秒响应(比如 time.Sleep(5 * time.Second)),再 Ctrl+C,看进程是否立刻消失、日志是否打印出 cancel 原因。如果没消失,说明至少有一个 goroutine 还在等它自己的“永远不来的信号”。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











