v1.1.0 v1.0.0 · 稳定根 GA · 扩展模块按成熟度标注 查看发布策略 →

框架对比

Go HTTP 工具包

Gin、Echo、Fiber、Chi 和 Plumego——每个框架放弃了什么,换来了什么。这页是决策辅助工具,不是基准测试排行榜。

从 Beego 或 Iris 迁移? 这页对比的是当前主流的五个轻量级 stdlib 兼容(或接近兼容)的工具包。 Beego 和 Iris 是更重的全栈框架:Beego 带 ORM、MVC 路由和内置 admin,Iris 带自定义 context 和插件系统。 如果你正从它们迁出,迁移到 Chi 或 Plumego 的路径是类似的——先把 handler 签名改回 func(w, r), 再逐步剥离框架特有的 context 用法。

30 秒快速结论。

五个工具包都针对 Go HTTP 服务。差异在于设计哲学和使用范围,而不是在典型请求量下的原始性能。 先看结论一行,再跟着符合你团队实际约束的深度分析走。

Gin

~80k ★

Martini 风格路由器,基数树路由

对于接受自定义 context 类型的团队,是最快上手的选择。生态丰富。很多 Go 团队的默认选项。

func(c *gin.Context)

Echo

~30k ★

高性能极简 Web 框架

API 整洁,中间件生态不错,handler 里 return error 的设计符合 Go 习惯。自定义 context 的权衡可以接受时,是个扎实的选择。

func(c echo.Context) error
Fiber 使用 Fasthttp,不是 net/http。与 Go 标准库 HTTP 生态完全不兼容。

Fiber

~34k ★

Express 风格,基于 Fasthttp

基准测试吞吐量最高。代价是与 net/http 完全不兼容——没有 stdlib 中间件、没有 net/http handler、没有标准库生态。

func(c *fiber.Ctx) error

Chi

~18k ★

轻量惯用的 Go HTTP 服务路由器

极简主义者的选择。纯 stdlib,对响应格式、服务结构或模块稳定性零主张。如果你想自己搭建所有东西,Chi 是合适的起点。

func(w http.ResponseWriter, r *http.Request)

Plumego

v1.0.0 ★

显式 HTTP 工具包 — stdlib only,Agent 就绪,v1.0.0

适合那些更看重路由 ownership、评审清晰度和共享服务骨架的团队,而不是框架便利性。如果团队在使用 AI 编码工具,这是唯一有机器可读 ownership 信号的选择。

func(w http.ResponseWriter, r *http.Request)

特性矩阵。

横向阅读一行,对比所有五个工具包的同一属性。矩阵不涵盖生态大小、社区活跃度或原始性能——这些取决于你的基准。它捕捉的是不随负载变化的结构性权衡。

属性 Gin Echo Fiber Chi Plumego
stdlib handler 签名 func(w http.ResponseWriter, r *http.Request)
net/http 中间件复用 已有 stdlib 中间件无需适配器
零外部依赖 稳定内核仅用 Go 标准库
内置响应 contract 成功与错误响应的类型化 JSON 封装
规范服务骨架 bootstrap、路由和 handler 布局的参考应用
显式模块稳定性层级 stable / beta / experimental 标签与采用指南
AI / Agent 就绪控制面 specs/task-routing.yaml 在代码打开前就对工作分类;specs/change-recipes/ 为 15 种修改类型定义有序步骤;module.yaml 约束每个包的范围;internal/checks/ 在 CI 中机械执行边界检查

Fiber 与 net/http 的不兼容性不是缺失的功能——这是换取更高吞吐量的刻意架构取舍。参见 Fiber 深度分析,了解这个权衡什么时候值得做。

Handler 签名是最关键的选择。

自定义 context 类型(Gin、Echo、Fiber)破坏了与已有 net/http 中间件生态的兼容性。 采用这些框架后,每个 stdlib 中间件都需要适配器。用 Chi 和 Plumego,整个 net/http 世界都能直接使用。

Gin 自定义 context
handler.go
// gin.Context — net/http 中间件需要适配器
r.GET("/users/:id", func(c *gin.Context) {
    id := c.Param("id")
    c.JSON(http.StatusOK, gin.H{"id": id})
})
// 复用 net/http 中间件需要:
r.Use(gin.WrapH(myStdlibMiddleware))
Echo 自定义 context
handler.go
// echo.Context + error 返回值
e.GET("/users/:id", func(c echo.Context) error {
    id := c.Param("id")
    return c.JSON(http.StatusOK,
        map[string]any{"id": id})
})
Fiber fasthttp — 非 net/http
handler.go
// fasthttp — 与 net/http 完全不兼容
// 零个 net/http 中间件可以复用
app.Get("/users/:id", func(c *fiber.Ctx) error {
    id := c.Params("id")
    return c.JSON(fiber.Map{"id": id})
})
Chi stdlib handler
handler.go
// 纯 stdlib — 但没有响应 contract
r.Get("/users/{id}", func(w http.ResponseWriter, r *http.Request) {
    id := chi.URLParam(r, "id")
    // 每次都要自己构建 JSON 响应格式
    json.NewEncoder(w).Encode(map[string]any{"id": id})
})
Plumego stdlib handler + contract
internal/handler/users.go
// stdlib 签名 + 类型化响应 contract
r.Get("/users/:id", func(w http.ResponseWriter, r *http.Request) {
    id := router.Param(r, "id")
    contract.WriteResponse(w, r, http.StatusOK, user, nil)
    // → {"data": {...}, "meta": null}
})

// 所有 net/http 中间件直接可用
r.Use(middleware.RequestID)
r.Use(myOtelMiddleware)

响应 contract:统一封装 vs. 自己构建。

Gin、Echo、Fiber 和 Chi 都把 JSON 响应格式留给你决定。这意味着每个团队、每个 handler 或每个项目的响应格式可能都微妙不同。 Plumego 的 contract 模块对成功和错误响应强制执行同一个封装。

Gin / Echo / Fiber / Chi — 各自决定格式

handler.go
// 成功响应 — 每个团队格式不同
c.JSON(200, gin.H{
    "data":    user,
    "success": true,   // 有些团队加
    "code":    0,          // 有些团队加
})

// 错误响应 — 更加不一致
c.JSON(400, gin.H{
    "error":   "name required",
    "message": "...",  // 重复?缺失?
    "code":    1001,
})

Plumego — 所有 handler 共用一套 contract

internal/handler/users.go
// 成功 — 始终是 {"data": ..., "meta": ...}
contract.WriteResponse(w, r, 200, user, nil)

// 错误 — 始终是 {"error": {"type": ..., "message": ...}}
contract.WriteError(w, r,
    contract.NewErrorBuilder().
        Type(contract.TypeRequired).
        Field("name").
        Message("name 是必填项").
        Build())

// 每个 handler、每个服务的封装都一致

各框架的选择指南。

下表不是为了评出胜者。每行回答两个问题:这个框架擅长什么,以及什么情况下应该暂停考虑。 「什么时候不该选 Plumego」的诚实回答在最后。

框架 选择场景 暂停场景
Gin
  • 需要最快速度跑起一个 API
  • 需要认证、限流等大量插件生态
  • 团队已经熟悉 gin.Context 及其权衡
  • 已有大量 Gin 代码,切换成本太高
  • 需要 handler 保持 func(w, r) 形式,让已有 stdlib 中间件无需适配器就能工作
  • 希望在代码评审里直接看到路由归属和中间件顺序,而不需要翻框架源码
  • 需要跨所有 handler 一致的结构化错误与响应封装
Echo
  • 更喜欢从 handler 返回 error 而不是直接写 w
  • 需要文档清晰、中间件支持好的框架
  • 团队欣赏路由分组和内置 binder/validator
  • 需要纯 net/http 兼容——echo.Context 破坏了中间件复用
  • 需要统一的 JSON 响应封装——Echo 把响应格式留给你自己决定
  • 需要跨多个团队共用一套规范服务骨架
Fiber ⚠ fasthttp
  • 原始 HTTP 吞吐量是主要瓶颈,且你有基准数据证明
  • 从零新建服务,没有任何需要集成的 net/http 中间件
  • 团队有 Fasthttp 经验,清楚这个不兼容性的权衡
  • 有任何 net/http 中间件、handler 或工具——一个都用不了
  • 使用基于 net/http 的可观测性、链路追踪或认证库
  • 团队以 Go 标准库为中心,期望标准库兼容性
Chi
  • 只需要路由——愿意自己实现响应封装、中间件和安全层
  • 需要纯 stdlib 兼容,不想要任何框架结构主张
  • 团队偏好最大灵活性,愿意自己构建维护周边层
  • 需要跨 handler 一致的响应封装,但不想自己实现
  • 需要快速上手的规范服务结构
  • 需要每个模块单独的成熟度信号
Plumego
  • 路由注册、中间件顺序和依赖 wiring 必须在代码评审里清晰可见
  • 多个服务需要从同一个规范骨架起步,而不是各自发明 bootstrap
  • 使用 AI 编码助手,需要明确的机器可读规则来定位变更归属
  • 需要区分稳定模块和实验性能力工作
  • 希望框架隐藏结构决策——Plumego 刻意保持显式
  • 已有大量 Gin/Echo 代码,迁移成本超过收益
  • 需要经过多年验证的 v1+ 长期使用记录
  • 服务是小脚本或短生命周期工具,结构开销不划算

什么时候不该选 Plumego。

这一节是 Plumego 自己的内容规则要求的。诚实的对比必须包含框架不合适的场景——不只是它赢的地方。

约定优先的团队

你希望框架替你管理结构

Plumego 把路由注册、中间件顺序和依赖 wiring 都明确地留在你的代码里。 如果团队更希望框架隐式管理结构,显式模型只会增加摩擦而没有额外价值。选 Gin 或 Echo 会更高效。

已有大型代码库

团队已经有大量 Gin/Echo 服务

把成熟的 Gin 或 Echo 服务迁移到 Plumego,需要把所有 handler 从自定义 context 改成 net/http 签名。 如果服务运行正常、团队工作顺畅,这个迁移成本几乎不值得。留在你已有的框架上。

最大吞吐量

原始 HTTP 吞吐量是你的主要瓶颈

Plumego 使用 net/http 兼容的 trie 路由器,开销极小但不为零,比 Fiber 的 Fasthttp 基线多一点。 如果你有测量数据证明 HTTP 路由是瓶颈(不是数据库、不是业务逻辑),那 Fiber 才是对的话题。

现在就需要长期生产记录

你需要经过验证的 v1+ 版本记录

Plumego 已有 v1.0.0 标签,9 个稳定根有兼容性承诺,但项目尚未积累 Gin 或 Echo 那样的长期生产记录。 如果"5年以上大规模验证"是硬性要求,Gin 或 Echo 在组织层面更安全。

关于性能基准的说明。

这几个框架的基准对比在网上广泛流传。阅读时请保持审慎。

Fiber 注意事项

Fiber 的性能优势来自 Fasthttp,而不是更好的路由

Fasthttp 通过复用 buffer 来避免标准库分配,在合成基准中产生可测量的吞吐量提升。 但如果你需要 net/http 中间件、使用标准库 HTTP 客户端对接同一服务,或者工作负载的瓶颈是数据库 I/O 而不是 HTTP 解析,这个提升就会消失。

Plumego 基准

Plumego 路由器与 net/http 性能相当——尚未正式发布基准数据

Trie 路由器无反射、无全局状态,设计目标是与 net/http 性能相当。与 Gin、Echo、Chi 的可重现基准尚未发布,请关注 issue tracker 中的基准路线图。

通用建议

以性能为由选框架之前,先对你的实际工作负载做性能分析

大多数 Go HTTP 服务的瓶颈在数据库往返、外部 API 调用或序列化——而不是路由器。 没有针对你的具体工作负载和目标规模的测量数据,纯粹基于性能选择框架很难站住脚。

迁移到 Plumego 的成本。

切换框架的决策不只是 API 人机工程学问题——还涉及 handler 改写、中间件替换和测试基础设施的调整。 下表对从各框架迁移到 Plumego 所需工作量给出诚实估算。

来源框架 成本 变化内容
Gin medium 所有 handler 需要从 gin.Context 改写为 func(w, r),中间件需要适配或替换。路由语法基本一致(/foo/:id 不变)。视 handler 数量,每个服务预计需要 1–3 天。
Echo medium 需要把 handler 从 echo.Context + error return 改写为 func(w, r)。路由分组概念映射较直接。中间件需适配器。与 Gin 迁移工作量相当,约 1–3 天每个服务。
Fiber high 需要完全重写。Fasthttp 与 net/http 从根本上不兼容——handler 无法复用、中间件无法复用、测试基础设施无法复用。可观测性、认证和链路追踪库全部需要替换。预计以周计,而非天。
Chi low Handler 签名完全相同(stdlib func(w, r))。路由语法略有差异:Chi 用 /foo/{id},Plumego 用 /foo/:id。中间件完全兼容。大多数服务的迁移以小时计,而非天。

迁移成本以现有 handler 和中间件的服务为基准。 从 reference/standard-service 全新搭建的服务没有迁移成本。

路由性能基准数据。

使用 go test -bench -benchmem -count=3 实测的顺序与并发调度数据。 路由:GET /users/:id,无中间件。linux/amd64,Intel Xeon @ 2.10 GHz。 包含完整 httptest 请求/响应周期。相对列以 Plumego 为基准(1.0×)。

路由开销很少是真正的瓶颈——数据库调用耗时 500 µs–5 ms,路由仅 1–5 µs。 选择框架时,以团队真正关注的因素为准。

Plumego vs Go stdlib 基准(http.ServeMux + PathValue()

开销来源:per-request context 注入(480 B,5 次分配)、参数映射构建以及中间件链接线。对于耗时 1 ms 的 I/O handler,路由开销低于请求总耗时的 0.1%。

测试场景 stdlib ns/op Plumego ns/op 倍数
静态路由 110 367 3.3×
单 :param + 读取 186 807 4.3×
四 :param 深路径 722 1036 1.4×
70 条路由混合表 247 660 2.7×

四参数深路径场景(1.4×)说明:随着路径复杂度增加,开销收敛——trie 遍历摊销到了更多工作量上。 复现:go test -bench=BenchmarkRouter -benchmem -count=3 ./reference/benchmark/...

顺序调度(ns/op)

框架 ns/op allocs/op B/op vs Plumego
Plumego 本项 4291 16 5715 1.0×
Chi 4547 17 6036 1.06×
Gin 更快 3773 13 5331 0.88×
Echo 更快 3743 13 5331 0.87×

并发吞吐 — b.RunParallel at GOMAXPROCS

框架 ns/op allocs/op B/op vs Plumego
Plumego 本项 663 7 592 1.0×
Chi 1013 8 912 1.53×
Gin 更快 285 4 208 0.43×
Echo 更快 231 4 208 0.35×

在同样兼容标准库的框架中(Chi 和 Plumego),Plumego 并发吞吐量领先 35%(663 vs 1,013 ns/op)。 Gin 和 Echo 在此测试中比 Plumego 快 ~2.5–3×,因为 sync.Pool context 消除了每次请求的内存分配——代价是使用与标准库中间件不兼容的自定义 context 类型。 如果 stdlib 兼容性对你的团队重要,最有意义的对比对象是 Chi,而不是 Gin 或 Echo。

复现方法:cd reference/benchmark && go test -bench=. -benchmem -count=3 ./...

做出决策了吗?

如果 Plumego 符合你团队的工作模式,从 reference app 开始。如果另一个框架更合适,那就是正确的选择——这页存在是为了帮你决策,不是为了推销。

还不确定是否适合? 阅读诚实的权衡评估 →