路由报错源于路径、方法、StrictRouting、参数声明四者未对齐;StrictRouting=true时/users与/users/视为不同路由;c.Params("id")仅从显式声明的占位符提取;app.Use前缀匹配,app.Group需写全路径;PUT/DELETE需JS发送;路由注册须在app.Listen()前完成。

路由报错不是 Fiber 抽风,而是路径、方法、StrictRouting、参数声明四者没对齐——少一个,404 或 405 就立刻出现,且不告诉你哪错了。
为什么 /users 和 /users/ 都 404?StrictRouting 是开关不是 bug
Fiber 默认 StrictRouting: true,/users 和 /users/ 是两条完全独立的路由。你只注册了 app.Get("/users", h),那访问 /users/ 必然 404。
- 别关
StrictRouting: false:它会触发尾斜杠归一化,导致/users/:id被/users拦截,c.Params("id")永远为空 - 推荐做法是加统一重定向中间件(放在所有路由注册前):
app.Use(func(c *fiber.Ctx) error { path := c.Path() if strings.HasSuffix(path, "/") && path != "/" { c.Redirect(strings.TrimSuffix(path, "/"), fiber.StatusMovedPermanently) return nil } return c.Next() }) - 上线前同步检查前端 SDK、OpenAPI spec、Postman 集合——全用无尾斜杠路径,后端只注册一种形式
c.Params("id") 总是空?参数提取不靠猜,只认显式声明
c.Params("id") 不是从 URL 字符串里“扫描”出来的,它只从你路由定义中明确写出的占位符里取值。没声明,就永远返回空字符串。
- 你注册的是
app.Get("/user/:id", h),才能在/user/123中拿到"123";访问/user?id=123或发 JSON body,c.Params一律无效 - 需要强校验 ID 格式?用
fiber.RegisterCustomConstraint("int", ...),别在 handler 里写if !isNumeric(c.Params("id")) - 调试时用
c.Route().Path打印当前匹配到的路由模板,确认是否真走到了你预期的 handler
app.Use() 和 app.Group() 混用导致路径错乱?前缀匹配有边界
app.Use("/api") 是前缀拦截,对所有 HTTP 方法生效;app.Group("/api") 是创建新路由树节点,后续路径必须写全,Fiber 不会帮你补前缀。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
-
api := app.Group("/api")后,要写api.Get("/users", h)→ 注册的是GET /api/users;写成api.Get("/api/users", h)就变成/api/api/users,多了一层 -
app.Use("/api", middleware)匹配/api、/api/users、/api/v1/health;但不匹配/apixxx或/api123(后面不是/或路径结束) - 组内中间件如
api.Use(auth)只影响该组,和全局app.Use()是隔离的
PUT/DELETE 请求总 405?先看 Network 面板里 Method 到底是不是真 PUT
浏览器原生 只支持 GET 和 POST,写 method="put" 会被忽略,退化成 GET——这不是 Fiber 的问题。
- 真
PUT/DELETE必须用 JS 发送:fetch("/api/user/123", { method: "PUT", body: JSON.stringify(data) }) - 打开浏览器 Network 面板,点开请求,看
Request Method列显示的是不是PUT,而不是只看代码里写的字符串 - Fiber 不做方法模拟,也不读
_method隐藏字段,不用配类似HiddenHttpMethodFilter的东西
最常被忽略的点:路由注册必须在 app.Listen() 之前完成。Radix 树启动后冻结,运行时调 app.Add() 会触发 fatal error: concurrent map writes;所有 app.Get()、app.Post() 都得放在 main() 顶部或初始化函数中。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










