中间件执行顺序严格由注册位置决定:app.Use()全局→Group参数中间件→路由级中间件;顺序错一位会导致c.Locals为空、日志缺失或鉴权失效;响应阶段逆序执行;分组中间件必须作为Group参数传入,group.Use()会注册错误路由而非中间件。

中间件执行顺序不是“自动排好”的,而是由 app.Use()、app.Group() 和路由注册时的代码位置严格决定的;顺序错一位,c.Locals 可能为空、日志打不出来、鉴权直接失效。
中间件注册顺序 = 请求时执行顺序
Fiber 不重排中间件,app.Use() 的调用顺序就是请求进入时的执行顺序。响应阶段则逆序执行(handler → 最后一个中间件 → 第一个中间件)。
- 常见错误现象:
panic: middleware A tried to access context value set by B, but B hasn't run yet——本质是 A 依赖 B 设置的c.Locals或c.UserContext(),但app.Use(A)写在了app.Use(B)前面 - 想让日志记录状态码?
logger.New()必须放在鉴权、业务 handler 之后,否则c.Response().StatusCode()还没写入 -
app.Use("/api", cors.New())不是“给 /api 分组加 CORS”,而是匹配所有以/api开头的路径(包括/api/static/logo.png),且对每个方法都单独注册一份中间件链 - 若同时有
app.Use(logger)和app.Use(auth),请求流是:logger → auth → handler;响应流是:handler → auth(返回阶段)→ logger(返回阶段)
分组中间件必须作为 Group 参数传入
app.Group("/admin", authMiddleware) 是唯一正确挂载方式;group.Use() 是陷阱,它会注册一条新路由而非中间件。
-
admin := app.Group("/admin"); admin.Use(authMiddleware)→ ⚠️ 错误:这实际注册了一条USE /admin/*路由,不作用于GET /admin,还可能和已有路由冲突 - 多个分组中间件按参数顺序执行:
app.Group("/api", logger, jwtAuth)→ 先logger,再jwtAuth - 分组中间件只影响该组内注册的路由,不影响根路径(如
/health)或其它分组 - 若某条路由需额外控制(如 IP 白名单),可单独加:
api.Get("/delete", ipWhitelist, handler),它会在分组中间件之后、handler 之前执行
路由级中间件只对当前路由生效,且不能乱调 c.Next()
用 app.Get("/x", mw, handler) 方式传入的中间件,签名必须是 func(*fiber.Ctx) error,且逻辑必须围绕 c.Next() 展开。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
- 别在
c.Next()后继续写业务逻辑——Fiber 已把控制权交出,后续只有 handler 执行完才会回来 - 鉴权失败必须显式
return,例如:c.Status(401).SendString("no"); return;千万别c.Next(),否则 handler 仍会执行 - 多个路由级中间件按参数顺序执行:
app.Get("/x", a, b, c, h)→ a → b → c → h - 路由级中间件一定在所有全局/分组中间件之后、handler 之前运行,无法“插队”到 logger 前面
CORS 和其他关键中间件必须前置注册
fiber.CORS()、recover.New()、requestid.New() 等中间件,必须在任何业务路由注册前调用,否则不生效。
-
app.Use(fiber.CORS())放在app.Get("/api/user", h)之后 → ❌ 完全无效 - 带
credentials: true时,AllowOrigins不能为"*",必须是具体域名切片,否则浏览器静默拦截 -
fiber.CORS()自动处理 OPTIONS 预检,但前提是前面没有中间件提前return(比如鉴权失败直接401就会跳过 CORS) - 如果用了
StrictRouting: true(默认开启),确保预检路径与业务路径完全一致,OPTIONS /api/user和OPTIONS /api/user/是两条不同路由
最容易被忽略的是:中间件顺序一旦写死在代码里,就无法靠配置或运行时调整;重构时若只改了分组前缀却忘了中间件注册位置,整个链路行为就会偏移——这不是 bug,是设计使然。

















