定位
Fiber 是基于 fasthttp 的 Go Web 框架,API 风格照搬 Express。它的卖点只有一个:快。
代价也明确:不兼容 net/http,所以整个 Go 标准库生态的中间件、监控、pprof 都用不了。
安装
go mod init example.com/fiber-demo
go get github.com/gofiber/fiber/v3
Fiber 已经到 v3,和 v2 的 API 有差异(主要是 Ctx 的方法签名和配置项)。网上大量教程还是 v2,抄代码时注意版本。
最小可运行示例
package main
import "github.com/gofiber/fiber/v3"
func main() {
app := fiber.New()
app.Get("/", func(c fiber.Ctx) error {
return c.SendString("Hello")
})
app.Get("/users/:id", func(c fiber.Ctx) error {
return c.JSON(fiber.Map{"id": c.Params("id")})
})
app.Listen(":8080")
}
核心概念
1. 一切围绕 fasthttp
fasthttp 为了性能做了激进优化:复用请求和响应对象,不遵循 net/http 的 Request / ResponseWriter 接口。
好处是快(内存分配少)。坏处是下面这条铁律。
2. 绝对不要持有 Ctx
// 错误:c 在 handler 返回后会被复用到下一个请求
app.Get("/bad", func(c fiber.Ctx) error {
go func() {
time.Sleep(time.Second)
log.Println(c.Params("id")) // 可能读到别人的请求数据
}()
return nil
})
// 正确:先把需要的值复制出来
app.Get("/ok", func(c fiber.Ctx) error {
id := c.Params("id") // string 是值拷贝,安全
go func() {
time.Sleep(time.Second)
log.Println(id)
}()
return nil
})
这是 Fiber 最容易出的事故:数据错乱、串号,而且难复现。凡是异步、goroutine、队列里用到请求数据的地方,都要先拷贝。
3. Express 式中间件链
app.Use(func(c fiber.Ctx) error {
start := time.Now()
err := c.Next() // 执行后续 handler
log.Printf("%s %s %v", c.Method(), c.Path(), time.Since(start))
return err
})
c.Next() 之前的代码在请求前执行,之后的在响应后执行——和 Express 完全一致。
4. 内置能力比 Gin 多
Fiber 自带静态文件、模板渲染、WebSocket、限流、压缩、CORS,不需要额外找中间件。这是对「生态不兼容」的补偿。
常见坑
① 用不了 net/http 中间件
Prometheus 的 promhttp、pprof、go-chi 的中间件、各种 APM 的 SDK——全部要自己写适配层。选 Fiber 前先列一遍你要用的第三方库。
② 参数绑定不区分类型
c.ParamsInt("id") 这类辅助方法会做转换,但默认值处理要自己写。不如 Gin/Echo 的 struct 绑定方便。
③ HTTP/2 支持不完整
fasthttp 对 HTTP/2 的支持有限。如果前面挂了 nginx 做 TLS 终结,通常没问题;直接对外提供 HTTP/2 要注意。
什么时候选它
- 追求吞吐量,压测数据是硬指标
- 团队从 Node.js/Express 过来,想零学习成本
- 内部服务,不需要大量第三方中间件
不选它的场景:需要标准库生态(监控、链路追踪、pprof)、团队里有人会踩「持有 Ctx」的坑而无法自查。
性能的现实
Fiber 的 benchmark 数据确实比 Gin 好看,但差距通常在 20-40%,不是数量级。而且这个差距在真实业务里几乎无感——你的接口耗时 5ms,其中框架开销 0.1ms 还是 0.07ms,用户看不出区别。
如果性能是你的核心诉求,先优化 SQL 和缓存,那才是 10 倍级的差距。