找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2979

积分

0

好友

388

主题
发表于 11 小时前 | 查看: 0| 回复: 0

在编程语言社区中,Go 语言常常因为其“繁琐”而饱受诟病。“if err != nil 写断手”、“缺乏语法糖”、“到处都是重复的样板代码”…… 这些似乎已经成为了 Go 的标签。

相比之下,Rust 往往被视为“表达力”的代表,拥有强大的宏、模式匹配和类型系统,能够用更少的代码做更多的事。然而,Ben Boyter 最近的一项硬核研究,通过分析 GitHub 上各语言 Top 100 仓库(总计约 4 亿行代码),得出了一个有趣的结论:在代码重复率和“样板代码”密度上,Go 和 Rust 几乎处于同一水平线。

不仅是行数:ULOC 指标

传统的 SLOC(源代码行数)往往无法真实反映项目的复杂度和冗余度。Ben Boyter 使用了他开发的工具 scc 中的一个特殊指标:ULOC (Unique Lines of Code,唯一代码行数)。

ULOC 指标通过剥离“结构性噪音”来更精准地衡量系统的真实复杂度。其计算逻辑如下:

  • 剔除结构化冗余:不仅排除了空行,还排除了单纯的闭合大括号行(})以及在不同文件中大量重复出现的公共引用代码(如 includeimport)。
  • 过滤文件级模板:有效识别并扣除在项目中每个文件顶部几乎完全相同的 License(许可证)声明头,避免这些非逻辑性的“样板文字”虚增代码总量。
  • 计入注释成本:与传统 SLOC 不同,ULOC 会保留注释统计。作者认为,注释与代码一样需要同等的维护精力,反映了开发者的思考过程,因此属于“有效工作量”。

通过这种方式计算出的 Dryness(干度),代表了剔除“语法支架”和“版权模板”后,真正的业务逻辑与注释在代码中的占比。百分比越高,说明重复代码越少,信息密度越高;百分比越低,说明“样板代码”或重复结构越多。

令人震惊的对比:Go vs Rust

让我们直接看数据(数据来源:GitHub Top 100 仓库分析,2026年2月):

语言 Dryness (干度)
Clojure 77.91%
Haskell 77.25%
Shell 72.24%
Java 65.72%
Rust 60.5%
C 59.71%
C++ 59.33%
Go 58.78%
C# 58.4%

发现了吗?Rust (60.5%) 和 Go (58.78%) 的差距微乎其微,甚至可以说在统计学上是等价的。

Ben Boyter 在文章中坦言,他之前也持有“Go 的样板代码比 Rust 多得多”的刻板印象。但数据表明,虽然两者的“啰嗦”方式不同,但结果是一样的:

  • Go 的啰嗦:体现在显式的错误处理、显式的循环结构,以及为了简单性而不得不写的重复逻辑。
  • Rust 的啰嗦:体现在复杂的类型系统设置、Trait 的实现(impl blocks)、以及为了满足借用检查器而编写的“仪式性”代码。

正如作者所总结的:

Go 狂热者:“Go 很简单!” -> “是的,简单到你需要把同一件事写很多遍。” Rust 狂热者:“Rust 完美表达!” -> “是的,但你花了 40% 的时间在写 setup 代码和 trait 实现。”

其他颠覆性的发现

除了 Go 和 Rust 的“握手言和”,这份报告还有几个极具冲击力的发现:

1. Lisp 家族是“干度之王”

Clojure 以 77.91% 的惊人密度位居榜首。Haskell 紧随其后。这验证了一个古老的观点:如果你想要最高的“人类思想 vs 击键次数”比率,Lisp 和函数式语言依然是王者。它们几乎每一行代码都是纯粹的业务逻辑。

2. Java 居然比 Go 和 Rust 都“干”?

Java 的得分为 65.72%,显著高于 Go、Rust 和 C#。这听起来反直觉,毕竟 Java 以 PublicStaticVoidMain 这种冗长著称。但这可能说明:

  • 现代 Java 及其生态(Spring 等)通过注解等方式极大地消除了样板代码。
  • 或者,Top 100 的 Java 项目多为成熟的业务系统,核心逻辑占比大,而 Go/Rust 项目中系统级代码(通常包含更多底层重复逻辑)较多。

3. 脚本语言的特异性

Shell Script 的密度极高(72.24%),但这主要是因为 Shell 脚本通常很短且高度定制化,很难复用,因此“唯一性”很高。

小结:复杂度的守恒

这个研究告诉我们一个道理:语言特性并不一定能消除复杂度,它往往只是转移了复杂度。

Go 选择了少量的特性,导致逻辑必须通过显式的重复代码来表达;Rust 选择了丰富的特性(宏、泛型、Trait),导致开发者必须编写大量的结构性代码来支撑这些特性。

对于 Gopher 来说,这或许是一种宽慰:别再为 if err != nil 感到羞愧了。隔壁写 Rust 的兄弟,虽然代码看起来很酷,但他们为了让编译器开心而敲击键盘的次数,并不比你少。

毕竟,软件工程没有银弹,只有取舍。

资料链接:https://boyter.org/posts/boilerplate-tax-ranking-popular-languages-by-density/


聊聊你的“啰嗦”体验

看完这个数据,你是感到“意料之中”还是“大吃一惊”?在你的实际开发中,你觉得 Go 的 if err != nil 更磨人,还是 Rust 的类型体操和 Trait 实现更让你头大?你认同“复杂度守恒”这个观点吗?欢迎在 开发者广场 分享你的看法。




上一篇:Claude Code Agent Team 模式深度解析:AI 集群协作实现系统级软件开发
下一篇:SoC DMA在嵌入式Linux中高效搬运USB数据的三种方案对比
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-9 20:36 , Processed in 0.422489 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表