必须显式配置 timeout 字段,否则 middleware.timeoutwithconfig 会 panic;超时后不会自动中断 db 查询或文件写入,需手动检查 ctx.isaborted() 做清理;全局或按路由组配置均需指定非零 timeout 值,且所有阻塞操作必须使用带超时的 context.context 显式传参并响应。

必须显式配置 Timeout 字段,否则 middleware.TimeoutWithConfig 会 panic;超时后不会自动中断 DB 查询或文件写入,得自己检查 ctx.IsAborted() 做清理。
全局超时配置要填满 Timeout 字段
直接调用 app.Use(middleware.TimeoutWithConfig(...)) 即可对所有请求生效,但结构体里的 Timeout 字段不能省略或为零值:
- 错误写法:
middleware.TimeoutWithConfig({})→ 启动就 panic - 正确写法:
Timeout: 5 * time.Second(单位必须是time.Duration) - 可选配
ErrorMessage和StatusCode,比如设成http.StatusRequestTimeout(408)或http.StatusGatewayTimeout(504) - 不设
ErrorMessage时,响应体默认是字符串"Timeout",不是空响应
按路由组设置不同超时阈值
Fiber 的 Group 不继承父级中间件,每个分组必须独立挂载 Timeout:
- 上传接口需要长超时:
upload := app.Group("/upload"); upload.Use(middleware.TimeoutWithConfig(middleware.TimeoutConfig{Timeout: 10 * time.Minute})) - API 接口要求快响应:
api := app.Group("/api"); api.Use(middleware.TimeoutWithConfig(middleware.TimeoutConfig{Timeout: 2 * time.Second})) - 注意:若先
app.Use(...)再建Group,该Group不会自动带上前面的中间件
超时触发后 handler 仍可能继续执行
Timeout 中间件只负责返回响应并标记 ctx.IsAborted() == true,但不会 kill 当前 goroutine 或回滚已执行的操作:
- DB 已写入?不会回滚 → 必须在业务逻辑里用
if ctx.IsAborted() { /* 清理 */ } - HTTP client 正在发请求?不会取消 → 所有下游调用必须用
ctx.Context()(不是c.Context()!而是你自己创建的带超时的context.Context)传参,例如httpc.Do(req.WithContext(ctx)) - 别依赖
c.Context().Done()判断超时,它只反映连接关闭,和Timeout中间件无关
常见误用导致超时完全失效
很多看似加了超时的写法,实际等于没加:
- 在 goroutine 里才调
context.WithTimeout→ 超时只杀 goroutine,主 handler 还卡着 - 用
db.QueryRow()而非db.QueryRowContext(ctx, ...)→ 驱动根本不读你的 context - 在超时后还调
c.SendString()→ 连接可能已被复用或关闭,会 panic 或静默失败 - 把
ctx.Next()放在超时判断之后却不 return → 即使已 abort,后续中间件仍可能执行
真正起作用的超时控制,从来不是靠中间件“喊一声”,而是靠你在 handler 里每一处阻塞操作都显式传入、监听、响应那个你亲手创建的 context.Context。











