
大家好,我是Tony Bai。
“Gin 就像是一种伪装成软件库的阴险真菌:它很容易感染,一旦沾上就几乎无法去除,除非你极其小心,否则还会传染给你的朋友。”
2025 年 12 月,Efron Licht 发布了一篇名为《Gin 是一个非常糟糕的软件库》的长文,用词之激烈、抨击之全面,瞬间引爆了 Go 社区。他将 Gin 比作“真菌”,并列举了从代码膨胀到 API 设计混乱的种种“罪状”。
这篇文章虽然充满了情绪化的发泄,但它同时也触及了许多资深 Gopher 心照不宣的痛点。Reddit 上的热烈讨论证明了这一点:虽然很多人不喜欢作者的语气,但绝大多数人承认他的技术批评是站得住脚的。
今天,让我们剥离情绪,结合社区的反馈,深入剖析这篇檄文背后的技术逻辑:作为 Go 生态中最流行的 Web 框架,Gin 真的有那么不堪吗?
第一宗罪:惊人的代码膨胀 (Code Bloat)
作者首先指出的,是 Gin 与其解决的问题之间巨大的比例失调。
标准库
net/http:仅用 2.5 万行 代码就实现了完整的 HTTP 协议栈(包含客户端、服务端、TLS 等)。Gin:为了实现路由和中间件等相对简单的功能,其依赖树竟然引入了 87 万行 代码和 55MB 的体积!
更令人咋舌的是,Gin 的依赖树中包含了至少 6 个不同的 JSON 库(包括 sonic, go-json, ugorji/go/codec 等)。一名Reddit 用户 证实了这一点,并指出即使在不使用 msgpack 的情况下,Gin 也会引入巨大的二进制开销。虽然可以通过 -tags nomsgpack 来缓解,但这并非默认行为。
这种“把厨房水槽都装进去”的依赖管理方式,对于追求简洁和二进制体积的 Go 项目来说,确实是一个沉重的负担。
第二宗罪:混乱的 API 设计与“抽象泄漏”
作者对 Gin 的 API 设计进行了无情的嘲讽,称其“表面积像工业散热器一样大,而且一样吸热(sucks)”。
gin.Context的过度设计:这个核心结构体拥有超过 133 个方法!它混杂了请求参数解析、响应写入、内容协商、Cookie 处理甚至 HTML 模板渲染等所有功能。一位Reddit 用户评论道:“Gin 就是当每一个可能的使用场景都塞进同一个库时发生的事情。”奇怪的方法签名:相比标准库清晰的接口,Gin 提供了数十种获取参数的方法,甚至还有
BindYAML,BindTOML等特定的绑定方法。这种设计不仅增加了学习成本,也让代码的可测试性大打折扣。
第三宗罪:致命的“锁定效应” (Lock-in)
这是作者认为最严重的问题,也是将其比作“真菌”的核心原因。
单向兼容性:你可以很容易地将一个标准的
http.Handler包装成 Gin 的 handler。无法逃离:但如果你想从 Gin 迁移回标准库,或者是迁移到其他框架(如 Chi, Echo),你会发现几乎不可能。因为你的业务逻辑已经深度耦合了
*gin.Context中那 100 多个特有的方法。
正如 一位Reddit 用户所言:“如果你想不付出巨大的开发者纪律和克制,就在 Go 中实现‘按需付费’(只引入需要的依赖),那几乎是不可能的。Gin 让事情变得简单,所以人们就用了它,尽管方式很糟糕。”
社区声音:不仅是批评,更是反思
Reddit 上的讨论为这场批判提供了更多元的视角:
“标准库至上”派的胜利:许多用户表示,他们早已放弃 Gin,转而投向 Echo 或 Chi。Chi 因为其极简的设计(仅 1000 多行代码)和对标准库接口的严格遵守,被多次点名表扬。
对“中间件地狱”的共鸣:一名用户指出,虽然标准库很美,但它的中间件链和上下文处理确实不如框架方便。Gin 的成功在于它填补了标准库在人体工程学 (Ergonomics) 上的空白,尽管是以一种臃肿的方式。
初学者的陷阱:多位用户提到,AI(如 ChatGPT)往往会默认推荐 Gin 给新手,导致许多内部服务和 API 仅仅因为“AI 推荐”就染上了这种“真菌”。这加剧了 Gin 的锁定效应。
小结:我们还需要 Gin 吗?
Efron Licht 的批评固然犀利,但也存在幸存者偏差。对于初学者或快速原型开发来说,Gin 提供的“一站式”体验(路由、参数绑定、验证、JSON 序列化)确实极大地降低了门槛。
然而,随着 Go 标准库的不断进化(特别是 Go 1.22 引入了增强的 http.ServeMux),以及像 Chi 这样更轻量且优秀的替代品的成熟,原生开发的体验已经今非昔比。
给 Go 开发者的一些建议:
对于新项目:建议评估 标准库 + Chi 或 Echo。它们提供了更好的模块化和更小的依赖负担。
对于已使用 Gin 的项目:不要恐慌,但要警惕。在编写 handler 时,尽量将
*gin.Context限制在最外层,将业务逻辑抽离到与框架无关的 Service 层中。警惕“便利性”陷阱:在引入任何“全家桶”框架之前,问自己一个问题:我引入的这 55MB 依赖,真的只是为了少写几行
if err != nil吗?
Go 的哲学是“少即是多”。Gin 在某种程度上,是对这一哲学的背离。这篇文章虽然激进,但它是一记警钟,提醒我们在享受便利的同时,不要忘记了软件工程中那些关于复杂性、依赖管理和可维护性的永恒真理。
资料链接:
https://eblog.fly.dev/ginbad.html
https://www.reddit.com/r/golang/comments/1pifcca/gin_is_a_very_bad_software_library/
如果本文对你有所帮助,请帮忙点赞、推荐和转发
!
点击下面标题,阅读更多干货!
- Go 也开始“叛逆”了?深度解读 JetBrains 2025 报告:为何“原生信仰”不再是唯一答案
- Go json/v2实战:告别内存爆炸,掌握真流式Marshal和Unmarshal
🚀 原「Gopher部落」已重装升级为「Go & AI 精进营」知识星球,快来加入星球,开启你的技术跃迁之旅吧!
我们致力于打造一个高品质的 Go 语言深度学习 与 AI 应用探索 平台。在这里,你将获得:
体系化 Go 核心进阶内容: 深入「Go原理课」、「Go进阶课」、「Go避坑课」等独家深度专栏,夯实你的 Go 内功。
前沿 Go+AI 实战赋能: 紧跟时代步伐,学习「Go+AI应用实战」、「Agent开发实战课」,掌握 AI 时代新技能。
星主 Tony Bai 亲自答疑: 遇到难题?星主第一时间为你深度解析,扫清学习障碍。
高活跃 Gopher 交流圈: 与众多优秀 Gopher 分享心得、讨论技术,碰撞思想火花。
独家资源与内容首发: 技术文章、课程更新、精选资源,第一时间触达。
衷心希望「Go & AI 精进营」能成为你学习、进步、交流的港湾。让我们在此相聚,享受技术精进的快乐!欢迎你的加入!👇

2357

被折叠的 条评论
为什么被折叠?



