必须通过fiber.Config{NotFound:...}传入fiber.New(),不能当作普通路由注册;需显式调用c.Status(404),避免异步渲染panic导致响应失败。

NotFound handler 为什么没生效
最常见原因是把它当普通路由注册,比如写 app.Get("/404", notFoundHandler)——Fiber 根本不会在路由未匹配时跳过去。它只在所有已注册路由都未命中、且中间件链没提前返回响应时才触发 NotFound。
另一个高频坑是:handler 里调了 c.Render("400", nil) 却没处理模板加载失败的 error,结果 panic 导致整个请求崩溃,连状态码都发不出去。
必须确保三件事:
-
NotFound是通过fiber.Config{NotFound: ...}传给fiber.New()的,不能后期覆盖 - handler 内必须显式调用
c.Status(404),否则浏览器看到 HTML 但状态码仍是 200 - 避免在
NotFound函数里用异步方法(如c.Render),应改用手动执行模板:engine.Execute(c.Context(), "404", nil, c.Response().BodyWriter())并捕获 error
ErrorHandler 怎么区分 404 和 500
ErrorHandler 负责捕获 panic 或显式抛出的 *fiber.Error,但它不负责“路由未匹配”——那是 NotFound 的事。两者职责不同,必须共存。
第三方 error(比如 os.Open 失败、数据库连接超时)没有自带状态码,如果直接 c.Status(500),就会把本该是 404 的未匹配错误也打成 500。
正确做法是先判断类型:
- 若
err是*fiber.Error,取它的.Code字段 - 否则统一设为 500,但可加日志记录原始 error 类型以便排查
- 别在
ErrorHandler里再调panic,否则会二次崩溃
StrictRouting 导致 /users/ 返回 404 怎么办
Fiber 默认 StrictRouting: true,意味着 /users 和 /users/ 是两条完全不同的路由。你只注册了 app.Get("/users", h),那访问 /users/ 必然 404。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
关掉 StrictRouting 不推荐:它会让 /users/:id 和 /users/ 冲突,导致参数提取失败。
更安全的解法是加统一重定向中间件(放在所有路由注册前):
- 检测
c.Path()是否以"/"结尾且长度大于 1 - 用
c.Redirect(strings.TrimSuffix(c.Path(), "/"), fiber.StatusMovedPermanently) - 注意保留 query string:需手动拼接,
c.Request().URI().FullURI()可辅助提取完整 URL
c.Params() 总是空,但 URL 看起来是对的
c.Params("id") 不是从 URL 里“自动提取”的,它只从你路由定义中明确写出的占位符里取值。没声明,就永远返回空字符串。
典型误配场景:
- 注册的是
app.Get("/user/:id", h),但访问的是/user/123/(结尾斜杠)→ StrictRouting 下不匹配 - 注册的是
/api/v1/post/:id,但访问的是/post/7→ 前缀不一致,根本不会进这个 handler - 用了通配符
/user/*,它会粗暴匹配所有子路径,干扰精确路由
调试时可用 c.Route().Path 打印当前匹配到的路由模板,确认是否真走到了你预期的 handler。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










