gin.default()默认无超时,需手动配置http.server的readtimeout、writetimeout和idletimeout;下游http调用须用自定义http.client设timeout;中间件应注入context.withtimeout控制handler内逻辑超时;gin.context与context.context不可混淆。

gin.Default() 默认不带超时控制,必须手动配置
直接用 gin.Default() 启动的服务,底层用的是 http.Server 默认配置,ReadTimeout、WriteTimeout 全为 0 —— 即无限等待。一旦后端依赖(如数据库、下游 HTTP 接口)卡住,连接会一直挂着,goroutine 不释放,最终耗尽资源。
正确做法是显式构造 http.Server 并设置超时参数:
-
ReadTimeout:从客户端读取请求头和 body 的最大时间(建议设为 5–10 秒) -
WriteTimeout:向客户端写响应的最大时间(建议 ≥ ReadTimeout,留出业务处理余量) -
IdleTimeout:keep-alive 连接空闲最大时间(建议 30–60 秒,防长连接堆积)
示例:
srv := &http.Server{
Addr: ":8080",
Handler: r,
ReadTimeout: 8 * time.Second,
WriteTimeout: 12 * time.Second,
IdleTimeout: 60 * time.Second,
}
srv.ListenAndServe()
下游 HTTP 调用必须用自定义 http.Client 控制超时
Gin 本身不干预你代码里怎么发 HTTP 请求。很多新手在 handler 里直接用 http.Get() 或 http.DefaultClient,这两个都默认无超时,极易拖垮整个服务。
关键点:
- 永远不要用
http.DefaultClient做下游调用 - 每个外部依赖应配独立
http.Client,避免超时策略互相干扰(比如用户服务可设 3 秒,文件服务可设 30 秒) - 超时应覆盖连接、写入、读取三阶段:
Timeout字段即可统一控制(等价于ConnectTimeout + WriteTimeout + ReadTimeout)
示例:
userClient := &http.Client{
Timeout: 3 * time.Second,
}
resp, err := userClient.Get("https://user-svc/api/user/123")
中间件中统一注入 context 超时,避免 handler 内部失控
仅靠 http.Server 级超时不够 —— 它只管连接生命周期,不管 handler 内部逻辑执行多久。比如一个 handler 里循环查数据库 5 次,每次 2 秒,总耗时 10 秒,但 WriteTimeout 是 12 秒,它仍能“合法”跑完,用户却等了太久。
推荐在中间件中对每个请求注入带超时的 context.Context:
- 用
context.WithTimeout(c.Request.Context(), 5*time.Second)创建子 context - 把该 context 传给 service 层、DB 查询、HTTP 调用等所有可能阻塞的操作
- 所有依赖库(如
database/sql、redis-go)都支持传入 context,超时后自动取消
注意:别在中间件里直接用 c.Request = c.Request.WithContext(...),Gin 的 c.Request 是只读封装,应通过 c.Set("ctx", ctx) 或更稳妥地——把 context 显式传入业务函数。
别混淆 gin.Context 和 context.Context,这是最常踩的坑
gin.Context 是 Gin 框架的请求上下文对象,封装了 HTTP 请求/响应、参数解析、中间件流转等;而 context.Context 是 Go 标准库的取消与超时控制机制,两者完全无关,不能互相替代。
典型错误:
- 以为调用
c.Done()就能控制 handler 超时(其实它只反映 HTTP 连接关闭信号) - 在 handler 里写
select { case 来做超时判断(这只会响应客户端断开,不是服务端主动超时) - 没把
context.Context传进 DB 查询,导致db.QueryContext(ctx, ...)没生效
真正起作用的是你手动创建并传递的那个 context.Context,它需要贯穿整个调用链 —— 从中间件 → service → repo → driver。











