标签 Unix 下的文章

Go 比 Python 更懂“Python 之禅”?

本文永久链接 – https://tonybai.com/2025/07/19/go-understand-the-zen-of-python-better-than-python

大家好,我是Tony Bai。

最近,在国外的 Go 语言社区(Reddit r/golang)上,一个帖子引发了热烈的讨论。标题颇具“引战”意味:“Go似乎比Python更好地实现了Python之禅”。

这听起来像个悖论,甚至有点冒犯。用一个语言的哲学去评判另一个语言,就像用“太极”的理念去评价“咏春”,似乎风马牛不相及。但仔细看完社区的讨论,你会发现这并非无稽之谈,反而是一个极其刁钻又深刻的视角,能帮助我们重新审视 Go 语言设计的底层逻辑。

作为一名在 Go 的世界里摸爬滚打了多年的老 Gopher,我也不止一次有过类似的感觉。今天,我们就借着这场社区热议,一起聊聊这个有趣的话题。

重温“Python之禅”

首先,让我们重温一下那首著名的“Python之禅”(The Zen of Python)。在任何一个 Python 解释器里输入 import this,你都能看到它:

The Zen of Python, by Tim Peters
Python之禅,作者:蒂姆·彼得斯

Beautiful is better than ugly.
优美优于丑陋。

Explicit is better than implicit.
显式优于隐式。

Simple is better than complex.
简单优于复杂。

Complex is better than complicated.
复杂优于繁杂。

Flat is better than nested.
扁平优于嵌套。

Sparse is better than dense.
稀疏优于密集。

Readability counts.
可读性至关重要。

Special cases aren't special enough to break the rules.
特例不足以特殊到足以打破规则。

Although practicality beats purity.
虽然实用性胜过纯粹性。

Errors should never pass silently.
错误绝不能悄无声息地被忽略。

Unless explicitly silenced.
除非显式地使其沉默。

In the face of ambiguity, refuse the temptation to guess.
面对歧义,拒绝猜测的诱惑。

There should be one-- and preferably only one --obvious way to do it.
应该有且最好只有一种显而易见的实现方式。

Although that way may not be obvious at first unless you're Dutch.
虽然这种方式一开始可能并不那么明显,除非你是荷兰人。

Now is better than never.
现在优于永不。

Although never is often better than right now.
虽然,永不去做常常比“马上”动手要好。

If the implementation is hard to explain, it's a bad idea.
如果实现很难解释,那么它是个坏主意。

If the implementation is easy to explain, it may be a good idea.
如果实现很容易解释,那么它可能是个好主意。

Namespaces are one honking great idea -- let's do more of those!
命名空间是个绝妙的主意——让我们多多地使用它吧!

这不仅仅是代码风格指南,更是一种编程哲学的宣言。而奇妙的是,当我们手握 Go 这把锤子时,会发现很多钉子恰好就是按照这份宣言的图纸来设计的。

“显式优于隐式”:Go 的灵魂,Python 的妥协

这是“Python之禅”中最核心的信条之一,也是 Go 语言最引以为傲(或被吐槽)的特征所在。

想想 Go 语言里最经典的 if err != nil。新手可能会觉得它繁琐、重复,破坏了代码的流畅性。但在经验丰富的工程师眼中,这正是“显式”的极致体现。每一次函数调用,你都被迫直面其可能失败的现实,错误处理的路径清晰得如同一条直线,没有任何隐藏的控制流跳跃。

相比之下,Python 的 try…except 机制虽然优雅,却在某种程度上是“隐式”的。一个 try 代码块里可能有多行代码,任何一行都可能抛出异常,然后被远处的某个 except 捕获。这使得控制流变得不再那么一目了然。一位 Reddit 用户评论说:“自从我见过那些数据科学代码后,‘显式优于隐式’这条让我笑出了声。” 这虽然是句玩笑,却精准地指出了在复杂项目中,隐式处理可能带来的维护难题。

Go 通过把错误(error)设计成普通的值,而不是一个特殊的控制流机制,完美践行了“显式优于隐式”的原则。它是你必须亲手处理的返回值,而不是可以被忽略的“天外来客”。

“简单优于复杂”:Go 的克制与执拗

Go 语言的设计者们(Rob Pike, Ken Thompson 等)深受 Unix 哲学的影响,对“简单”有着近乎偏执的追求。

  • 语法克制:Go 只有一个循环关键字 for,没有 while 或 do-while。它没有类和继承,取而代之的是更纯粹的组合与接口。并发模型也异常简单——go 关键字启动一个 goroutine,chan 进行通信,大道至简。
  • 工具统一:gofmt 的存在,终结了所有关于代码格式的“圣战”。它体现了“Python之禅”中的另一条原则:“应该有且最好只有一种显而易见的实现方式”。在 Go 的世界里,代码风格不是一个需要讨论的问题,这极大地降低了团队协作的认知负荷。

反观 Python,随着其生态的繁荣和应用领域的扩张,语言本身不可避免地变得越来越复杂。从最初与 Perl、PHP 竞争的简洁脚本语言,到如今涵盖 Web 开发、数据科学、AI 的庞然大物,它引入了 async/await、复杂的元编程能力等。这并非坏事,而是语言成熟和演化的必然结果。但与诞生之初就目标明确(解决 Google 内部大规模工程问题)的 Go 相比,Python 在“保持简单”这条路上,显然背负了更沉重的历史包袱。

客观看待:Go 的“禅意”并非没有代价

当然,我们不能一边倒地吹捧。Reddit 的讨论中也充满了理性的声音。Go 为了实现这种“禅意”,也付出了相应的代价。

  • “优美优于丑陋”(Beautiful is better than ugly):美是主观的。很多人认为 Go 的语法过于朴素,if err != nil 更是“丑陋”的代名词。但正如一位评论者所言:“我喜欢它,正是因为它在美学上很中庸(aesthetically mid)。” Go 的美,更多是一种“工程之美”,是结构清晰、易于维护、性能可靠的美,而非语法糖堆砌出的“华丽之美”。
  • “模板代码”(Boilerplate):Go 的“显式”和“简单”,直接导致了更多的模板代码。这是为了可读性和可维护性做出的权衡。社区也意识到了这一点,因此 Go 在泛型等方面的引入,以及强大的代码生成工具生态,都是在弥补这一“短板”。

小结:源于血脉的哲学共鸣

那么,为什么 Go 会比它的“老师” Python 更像一个“禅宗信徒”呢?

答案可能在它的“血脉”里。Go 的设计者们是创造了 C 语言、Unix 和 UTF-8 的传奇人物。他们骨子里流淌的是系统编程的血液,追求的是在数十、上百乃至上千工程师协作的大型项目中,如何保证代码的长期可读性、可维护性和稳定性。

这种背景决定了 Go 的设计哲学必然倾向于:明确、简单、组合、正交

它不追求用最少的代码行数表达最复杂的逻辑(那是 Python 的强项),而是追求让任何一个中等水平的工程师都能在最短时间内读懂并安全地修改代码。

从这个角度看,Go 并非“碰巧”契合了“Python之禅”,而是它的核心设计目标——工程化与可维护性——恰好与“Python之禅”所倡导的清晰与简洁产生了深刻的共鸣。可以说,Go 是在用一种更底层、更工程化的方式,对“Python之禅”进行了重新演绎。

所以,回到最初的问题:“Go 比 Python 更懂‘Python之禅’吗?”

或许,更准确的说法是:Go,在它所专注的领域里,以一种更为决绝和纯粹的方式,活成了“Python之禅”希望的样子。

对此,你怎么看?欢迎在评论区留下你的想法。

资料链接:https://www.reddit.com/r/golang/comments/1m302i6/go_seems_to_accomplish_the_zen_of_python_way


你的Go技能,是否也卡在了“熟练”到“精通”的瓶颈期?

  • 想写出更地道、更健壮的Go代码,却总在细节上踩坑?
  • 渴望提升软件设计能力,驾驭复杂Go项目却缺乏章法?
  • 想打造生产级的Go服务,却在工程化实践中屡屡受挫?

继《Go语言第一课》后,我的《Go语言进阶课》终于在极客时间与大家见面了!

我的全新极客时间专栏 《Tony Bai·Go语言进阶课》就是为这样的你量身打造!30+讲硬核内容,带你夯实语法认知,提升设计思维,锻造工程实践能力,更有实战项目串讲。

目标只有一个:助你完成从“Go熟练工”到“Go专家”的蜕变! 现在就加入,让你的Go技能再上一个新台阶!


商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。

Go 1.25链接器提速、执行文件瘦身:DWARF 5调试信息格式升级终落地

本文永久链接 – https://tonybai.com/2025/05/08/go-dwarf5

大家好,我是Tony Bai。

对于许多Go开发者来说,调试信息的格式可能是一个相对底层的细节。然而,这个细节却对编译速度、最终可执行文件的大小以及调试体验有着深远的影响。经过长达六年的讨论、等待生态成熟和密集的开发工作,Go 语言工具链终于在主干分支(预计将包含在 Go 1.25 中)默认启用了 DWARF version 5 作为其调试信息的标准格式(Issue #26379)。这一看似“幕后”的变更,实则为 Go 开发者带来了切实的链接速度提升可执行文件体积的优化。在这篇文章中,我们就来对DWARF5落地Go这件事儿做一个简单的解读。

为何需要升级到 DWARF 5?旧格式的痛点

DWARF (Debugging With Attributed Record Formats) 是类 Unix 系统上广泛使用的调试信息标准。Go 之前使用的 DWARF 版本(主要是 v2 和 v4)虽然成熟,但在现代软件开发实践中暴露出一些不足:

  1. 大量的重定位 (Relocations): 旧版 DWARF 格式通常包含大量需要链接器处理的地址重定位信息。根据 2018 年的初步分析(by aclements),在当时的 go 二进制文件中,高达 49% 的重定位条目都源于 DWARF 数据。这显著增加了链接器的工作负担,拖慢了构建速度,尤其是对于大型项目。
  2. 冗长的位置和范围列表 (Location/Range Lists): 用于描述变量生命周期和代码范围的 .debug_loc 和 .debug_ranges 等section的数据在旧格式下可能非常庞大。即便经过压缩,它们也能占到可执行文件大小的相当一部分(例如,当时 go 二进制的 12MiB 中占 6%)。
  3. 缺乏官方 Go 语言代码: 虽然不影响功能,但 DWARF 5 正式为 Go 语言分配了官方的语言代码 (DW_LANG_Go)。

DWARF 5 标准针对这些痛点进行了改进,其关键优势在于:

  • 位置无关表示 (Position-Independent Representations): DWARF 5 引入了如 .debug_addr, .debug_rnglists, .debug_loclists 等新 Section 格式,它们的设计能大幅减少甚至消除对重定位的需求,从而减轻链接器负担。
  • 更紧凑的列表格式: 新的列表格式 (.debug_rnglists, .debug_loclists) 比旧的 (.debug_ranges, .debug_loc) 更为紧凑,有助于减小调试信息的大小。

从提案到落地:漫长的等待与集中的开发

尽管 DWARF 5 的优势显而易见,但 Go 社区在 2018 年提出该想法时(by aclements),整个开发工具生态(如调试器 LLDB、macOS 的链接器和 dsymutil 工具等)对其支持尚不完善。因此,该提案被暂时搁置,等待时机成熟。

近年来,随着主流工具链(GCC 7.1+, GDB 8.0+, Clang 14+)纷纷将 DWARF 5 作为默认选项,生态环境逐渐成熟。Go 团队成员 Than McIntosh 承担了将 Go 工具链迁移到 DWARF 5 的主要开发工作。这涉及对编译器 (cmd/compile) 和链接器 (cmd/link) 的大量修改,引入了新的 GOEXPERIMENT=dwarf5 实验开关进行测试,并提交了一系列相关的变更集 (CLs),包括:

  • 添加 DWARF 5 相关常量和 relocation 类型定义。
  • 实现对 .debug_addr, .debug_rnglists, .debug_loclists section 的生成和支持。
  • 更新 DWARF 5 的行号表 (line table) 支持。
  • 适配 x/debug/dwtest 和 internal/gocore 等内部库。
  • 协调 Delve 调试器对 DWARF 5 的支持。

成果显著:链接速度提升与体积优化

经过广泛的测试和 compilebench 基准评估,启用 DWARF 5 带来了可观的性能收益:

  • 链接速度显著提升: ExternalLinkCompiler 基准测试显示链接时间减少了 约 14%。这主要得益于 DWARF 5 减少了链接器需要处理的重定位数量。
  • 可执行文件体积减小: HelloSize 和 CmdGoSize 基准显示最终可执行文件大小平均减小了 约 3%。这归功于 DWARF 5 更紧凑的列表格式。
  • 编译时间略有改善: 整体编译时间 (geomean) 也有约 1.9% 的小幅提升。

虽然对代码段 (.text)、数据段 (.data)、BSS 段的大小几乎没有影响,但链接耗时和最终文件大小的优化对于大型项目和 CI/CD 流程来说意义重大。

挑战与妥协:并非所有平台一步到位

在推进 DWARF 5 的过程中,也遇到了一些平台兼容性问题,导致 Go 团队采取了审慎的策略:

  1. macOS dsymutil 限制: 旧版本的 macOS Xcode 自带的 dsymutil 工具(用于处理和分离 DWARF 信息)不支持 DWARF 5 新引入的 .debug_rnglists 和 .debug_loclists section。这会导致在使用外部链接 (external linking) 构建 CGO 程序时,Go 代码的调试信息丢失。虽然 LLVM 17 (对应 Xcode 16+) 已修复此问题,但考虑到仍有大量开发者使用旧版 Xcode(官方支持最低到 Xcode 14),Go 团队决定在 macOS 和 iOS 平台上进行外部链接时,暂时回退到 DWARF 4。未来当最低支持的 Xcode 版本兼容 DWARF 5 后,有望统一。
  2. AIX 平台限制: AIX 使用的 XCOFF 文件格式本身不支持 DWARF 5 所需的 Section 类型。因此,AIX 平台将继续使用 DWARF 4 (GOEXPERIMENT=nodwarf5 默认开启)。
  3. GNU objdump 兼容性: objdump 工具在解析 Go 生成的 monolithic .debug_addr section 时会打印警告(因为它期望每个编译单元都有一个 header,而 Go 链接器只生成一个)。这被认为是一个 objdump 的小问题(已提议向上游提交修复),不影响实际功能,因此 Go 团队决定继续采用 monolithic 方式。

对开发者的影响与总结

对于大多数 Go 开发者而言,这项变更将在 Go 1.25 及以后版本中默认生效(除了上述 macOS 外部链接和 AIX 平台)。你将自动享受到更快的链接速度略小的可执行文件

  • 调试体验: 虽然 DWARF 5 本身设计更优,但对日常使用 Delve 等调试器的直接体验影响可能不明显,主要好处体现在工具链效率和文件大小上。
  • 注意事项: 如果你在 macOS 上进行 CGO 开发并使用外部链接,或者面向 AIX 平台,需要了解调试信息格式仍将是 DWARF 4。

总而言之,Go 工具链采纳 DWARF 5 是一个重要的里程碑。它不仅解决了旧格式的一些固有问题,提升了构建效率,也是 Go 语言紧跟底层技术标准发展、持续优化开发者体验的重要一步。这项历时多年的工作最终落地,体现了 Go 社区在推动技术演进方面的耐心和决心。

参考资料


聊聊你的编译构建体验

Go 1.25 工具链的这项 DWARF 5 升级,虽然“藏”在幕后,但实实在在地为我们带来了链接速度和文件大小的优化。你在日常的 Go 项目开发中,是否也曾被编译链接速度或可执行文件体积困扰过? 你对 Go 工具链在这些方面的持续改进有什么期待或建议吗?或者,你是否了解其他能有效优化构建体验的技巧?

欢迎在评论区分享你的经验、痛点与期待! 让我们共同见证 Go 工具链的进步。

想深入探索Go的编译、链接与底层奥秘?

如果你对 Go 工具链如何工作、编译优化、链接器原理,乃至像 DWARF 这样的底层细节充满兴趣,希望系统性地构建对 Go 语言“从源码到可执行文件”全链路的深刻理解…

那么,我的 「Go & AI 精进营」知识星球 正是为你打造的深度学习平台!这里有【Go原理课】带你解密语言核心机制,【Go进阶课】助你掌握高级技巧,更有【Go避坑课】让你少走弯路。我会亲自为你解答各种疑难问题,你还可以与众多热爱钻研的Gopher们一同交流,探索Go的更多可能,包括它在AI等前沿领域的应用。

扫码加入,与我们一同潜入Go的底层世界,成为更懂Go的开发者!

img{512x368}


商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言进阶课 AI原生开发工作流实战 Go语言精进之路1 Go语言精进之路2 Go语言第一课 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats