上线必须用 fiber.New() 而非 fiber.Default(),否则默认中间件导致敏感日志全量输出、I/O 瓶颈、TTFB 增加 0.3–0.8ms;StrictRouting 应通过显式注册或重定向处理尾部斜杠;c.QueryParam、c.Params、c.FormValue 来源不同不可混用;c.BodyParser 必须传结构体地址且需手动错误处理。

上线前不改 fiber.New() 而继续用 fiber.Default(),等于把 Authorization 头、完整请求体、每秒数百条日志全打到磁盘或 stdout,TTFB 多 0.3–0.8ms,高并发下 I/O 成瓶颈——这不是框架慢,是初始化错了。
fiber.New() vs fiber.Default() 怎么选
开发阶段用 fiber.Default() 没问题,它自动挂了 Logger、Recover、RequestID,适合快速验证逻辑;但上线必须切到 fiber.New(),它是空应用,什么中间件都不带。
- 用
fiber.Default()上线 → 每秒几百条含敏感头的完整请求日志,I/O 拖垮 QPS - 真要日志 → 改用采样式(比如只记 error)或对接结构化日志系统,别用
fiber.Logger() - 权限中间件里写完
c.Status(401).SendString("unauthorized")后,必须return,不能跟next(c)—— 响应已发出,Fiber 会终止链路
StrictRouting 导致 /users 和 /users/ 404 怎么办
Fiber 默认开启 StrictRouting: true,把 /users 和 /users/ 当作两个路由。你只注册了 app.Get("/users", handler),那访问 /users/ 就必然 404。
- 别全局关掉:
fiber.New(&fiber.Config{StrictRouting: false})→ 可能导致/users/123被/users错误匹配,c.Params("id")拿不到值 - 推荐显式注册两条:
app.Get("/users", handler)和app.Get("/users/", redirectHandler) - 或加统一重定向中间件:
if strings.HasSuffix(c.Path(), "/") && c.Path() != "/" { c.Redirect(strings.TrimSuffix(c.Path(), "/"), 301) }
c.QueryParam、c.Params、c.FormValue 到底读哪来的值
三者来源完全不同,混用必空:
-
c.QueryParam("q")只读 URL query string,比如/search?q=go中的q -
c.Params("id")只读路由占位符,比如app.Get("/user/:id", )匹配/user/123后的123 -
c.FormValue("name")是给application/x-www-form-urlencoded准备的;JSON body 必须用c.BodyParser(&v)或json.Unmarshal(c.Body(), &v)
c.BodyParser(&v) 解析 JSON 为什么总失败
c.BodyParser() 不会自动反序列化,必须显式调用,且传的是结构体地址:
- 错误写法:
c.BodyParser(v)(没取地址)→v保持零值,无报错 - 正确写法:
err := c.BodyParser(&user),其中user是 struct 变量名,前面带& - 解析失败时
err通常是json.Unmarshal错误(字段类型不匹配、缺json:tag),不是 HTTP 400 自动返回 - 别指望中间件自动做这事 —— Fiber 默认不注册 JSON 解析中间件
最常被忽略的是:所有中间件和 handler 里,一旦写了响应(c.JSON、c.SendString、c.Status(404).Send()),就必须 return,否则后续代码可能覆盖状态码或响应体;而 ctx.Next() 的语义不是“继续执行”,是“交还控制权”,是否往下走取决于当前 handler 是否已写响应。


















