标签 垃圾回收 下的文章

超越时间的智慧:重读那些定义了现代软件开发的经典文章

本文永久链接 – https://tonybai.com/2025/10/04/the-software-essays-that-shaped-me

大家好,我是Tony Bai。

二十年前,一位年轻的程序员在还未踏入职场时,便开始沉浸于软件开发的博客文章与深刻思考之中。二十年后,他已成为一名资深工程师,回首望去,成千上万的文字中,只有寥寥数篇真正沉淀下来,如基石般塑造了他的思维方式和职业生涯。

这份由 Michael Lynch 精心筛选出的“思想塑造清单”,本身就是一次对软件工程领域永恒智慧的巡礼。清单中的每一篇文章,都如同一个思想的火种,点燃了关于工程文化、代码哲学、乃至技术选型的深刻辩论。

今天,也让我们重新打开这些经典,逐一剖析其中的智慧,看看它们在瞬息万变的当下,能为我们——尤其是追求简约与高效的 Go 开发者——带来怎样历久弥新的启示。

1. Joel 测试:衡量开发者幸福感的 12 条黄金标准

(“The Joel Test: 12 Steps to Better Code” by Joel Spolsky, 2000)

Joel Spolsky 的这 12 个问题,与其说是对代码质量的测试,不如说是一面镜子,映照出一家公司是否真正尊重开发者的时间和心智。二十多年过去了,这些问题依然是衡量一个工程团队成熟度的“试金石”。

  1. Do you use source control? (你用源码控制吗?)
  2. Can you make a build in one step? (你能一步构建吗?)
  3. Do you make daily builds? (你每天都构建吗?)
  4. Do you have a bug database? (你有 Bug 数据库吗?)
  5. Do you fix bugs before writing new code? (你先修 Bug 再写新代码吗?)
  6. Do you have an up-to-date schedule? (你有最新的排期吗?)
  7. Do you have a spec? (你有需求规格说明吗?)
  8. Do programmers have quiet working conditions? (程序员有安静的工作环境吗?)
  9. Do you use the best tools money can buy? (你用钱能买到的最好工具吗?)
  10. Do you have testers? (你有测试人员吗?)
  11. Do new candidates write code during their interview? (新候选人在面试时会写代码吗?)
  12. Do you do hallway usability testing? (你做“走廊可用性测试”吗?)

虽然“每日构建”在今天已被“持续集成”(CI) 所取代,“Bug 数据库”也演变成了 Jira 或 Linear,但其精神内核——减少摩擦、自动化、系统化地管理混乱——从未过时。对于 Go 开发者而言,go build 的一步构建、go test 的内置测试、以及强大的静态分析工具链,都是对“Joel 测试”精神的现代回应。当你评估一个团队或项目时,不妨在心中过一遍这 12 个问题,它的得分,往往比任何花哨的技术栈更能说明问题。

2. 解析,而非验证:用类型系统构建“安全默认”的代码

(“Parse, don’t validate” by Alexis King, 2019)

这篇文章的核心论点,对于任何一个使用静态类型语言(如 Go)的开发者来说,都具有革命性的意义:“每当你验证一段数据时,你应该将它转换成一个新的类型。”

传统(脆弱的)做法:

// 每次使用前,都得记得调用它
func validateUsername(username string) error { ... }

这种做法的问题在于,它将验证的责任推给了开发者。你必须在代码的每一个角落,都记得去调用 validateUsername,一旦遗漏,就可能导致安全漏洞或数据损坏。

“解析,而非验证”的哲学:

// 定义一个全新的、无法被随意创建的类型
type Username string

// 唯一的入口:一个“解析”函数,它在内部执行验证
func ParseUsername(raw string) (Username, error) {
    if err := validate(raw); err != nil {
        return "", err
    }
    return Username(raw), nil
}

// 后续的业务逻辑,只接受这个被“祝福”过的类型
func GreetUser(u Username) { ... }

这种模式利用类型系统,将安全检查从一种“需要开发者时刻牢记的纪律”,转变为一种“由编译器强制执行的保证”。一旦你有了一个 Username 类型的变量,你就拥有了一个不可辩驳的证明——它必然是合法的。这在 Go 中极易实现,通过创建新的具名类型,我们可以轻松地在代码中构建起一道道安全的“防火墙”,让非法状态根本没有机会存在

3. 无银弹:正视软件开发的“本质复杂性”

(“No Silver Bullet” by Fred Brooks, 1986)

这篇来自《人月神话》作者的经典文章,将软件开发工作划分为两个核心部分:

  • 本质复杂性 (Essential Complexity):与问题领域本身固有的、不可简化的复杂逻辑作斗争。例如,设计一套复杂的保险计价公式。
  • 偶然复杂性 (Accidental Complexity):与工具、环境和实现细节作斗争。例如,处理内存泄漏、等待编译、配置构建系统。

Brooks 的核心论点是:过去几十年软件开发效率的巨大提升,主要来自于对“偶然复杂性”的削减。但无论工具如何发展,我们永远无法消除“本质复杂性”。因此,不存在任何能够带来数量级生产力提升的“银弹”

这篇文章是对抗技术领域“炒作周期”的最佳解毒剂。无论是微服务、Serverless、还是当下的 AI,它们在很大程度上解决的都是“偶然复杂性”。Go 语言的诞生,其核心目标——极快的编译速度、简单的并发模型、自动的垃圾回收——本身就是对 C++ 等语言“偶然复杂性”的一次宣战。

Brooks 的理论让我们保持清醒:即使 AI 能为我们编写代码,但定义需求、设计系统、测试复杂交互这些“本质复杂性”的工作,依然是人类工程师不可替代的价值所在。

4. 选择的代价:为用户做明智的决定

(“Choices” by Joel Spolsky, 2000)

Joel Spolsky 敏锐地指出:“你每提供一个选项,就是在要求用户做一次决策。” 过多的选择,尤其是那些用户并不具备足够信息来做出的选择,会中断用户的心流,带来挫败感。

他以 Windows 98 中一个荒谬的帮助搜索设置为例,痛斥了将底层技术决策(如“最小化数据库大小”或“最大化搜索能力”)推给普通用户的设计懒政。

这个原则不仅适用于 GUI,更适用于我们编写的任何 API 和命令行工具。当你的函数需要一大堆配置参数时,问问自己:

  • 这些选项真的都是必需的吗?
  • 我是否可以根据大多数场景,提供一个明智的、开箱即用的默认行为?
  • 对于必须暴露的选项,我能否通过 Go 的选项模式 (Options Pattern) 来组织它们,让简单的使用保持简单,让复杂的配置成为可能?

一个优秀的 API 设计者,应该是一个“仁慈的独裁者”,敢于为用户承担决策的责任,只在真正必要时,才将选择的权力交还给他们。

5. 兼容性是为用户,而非为程序

(“Application compatibility layers are there for the customer, not for the program” by Raymond Chen, 2010)

Raymond Chen 用一个尖刻的比喻,讽刺了那些期望操作系统为他们的旧软件提供无限向后兼容性的开发者。然而,文章作者 Michael Lynch 反思后认为,这个比喻的背后,其实蕴含着一个更深刻的用户行为洞察:用户永远会选择阻力最小的路径

如果你发现用户在以一种“错误”但“有效”的方式使用你的系统(比如,依赖一个 Bug 来实现某个功能),那么你的责任不是嘲笑他们,而是去理解他们为何这么做,并提供一条更简单、更正确的路径来引导他们。

这条规则对我们如今进行API设计也是大有借鉴意义的,这意味着我们需要时刻保持同理心。如果你发布了一个有 Bug 的 v1 版本,并且发现大量用户已经围绕这个 Bug 构建了他们的系统,那么在 v2 版本中,简单地“修复”这个 Bug 可能会导致大规模的破坏。

一个更负责任的做法可能是:

  1. 在 v2 中提供一个新的、行为正确的 API。
  2. 保留 v1 的旧 API,但将其标记为废弃,并在文档中清晰地解释其错误行为和迁移路径。
  3. (在 Go 1.26+ 中)甚至可以利用 //go:fix 指令,为用户提供自动化的迁移工具。

6. 不要在测试中引入逻辑

(“Don’t Put Logic in Tests” by Erik Kuefler, 2014)

我们通常被教导要在生产代码中遵循 DRY (Don’t Repeat Yourself) 原则。但 Erik Kuefler 指出,将这一原则盲目地应用到测试代码中,可能是一场灾难。

糟糕的测试:

// 为了“ DRY ”,我们拼接了 URL
assertEquals(baseUrl + "/u/0/photos", nav.getCurrentUrl());

这段代码隐藏了一个微小的 Bug(多了一个斜杠),因为它需要读者在脑中进行一次字符串拼接运算才能发现问题。

优秀的测试:

// 清晰、直白,一眼就能看出期望的结果
assertEquals("http://plus.google.com//u/0/photos", nav.getCurrentUrl());

虽然存在字符串冗余,但它的意图是一目了然的。

测试代码的首要目标是清晰性,而非优雅或无冗余。测试代码没有它自己的测试,验证其正确性的唯一方式就是人工审查。因此,一段好的测试,应该像一篇优秀的规格说明文档,让任何一个读者都能毫不费力地理解它在断言什么。在 Go 的表驱动测试 (Table-Driven Tests) 中,这一点体现得尤为重要:绝大多数情况下,输入和期望的输出应该被清晰地、并排地列出,而不是通过复杂的辅助函数动态生成。

7. 一点原生 JavaScript 就能做很多事

(“A little bit of plain Javascript can do a lot” by Julia Evans, 2020)

Julia Evans 曾分享了她从一个坚定的“前端框架拥护者”转变为“原生 JavaScript 爱好者”的心路历程。在饱受了 Angular, React, Vue 等框架带来的依赖问题和复杂性的折磨后,她决定尝试只用原生 JavaScript(现代的 ES2018 标准)来构建一个 Web 界面。

结果令她震惊:没有框架、没有构建步骤、没有 Node.js,她依然能完成 90% 的工作,而开发体验的“头痛程度”只有 5%。当出现运行时错误时,她看到的不再是经过压缩、转换的“天书”,而是她自己写的、清晰可辨的代码。

这篇文章是对现代软件开发中“框架至上”文化的一次有力反思。它提醒我们,在引入任何一个大型框架或库之前,都应该先问自己:我真的需要这个吗?标准库或语言本身的能力是否已经足够?

对于 Go 开发者而言,这种思想更是与语言的哲学不谋而合。Go 拥有一个极其强大的标准库(特别是 net/http),在许多场景下,你完全不需要引入像 Gin 或 Echo 这样的 Web 框架,就能构建出高性能、可维护的 Web 服务。

Julia 的经历鼓励我们,要敢于挑战对框架的“路径依赖”,重新审视并信任我们手中工具(无论是 JavaScript 还是 Go 标准库)的内建能力。有时候,最简单的解决方案,恰恰就在我们眼前。

8. 选择无聊的技术

(“Choose Boring Technology” by Dan McKinley, 2015)

这篇经典文章的标题本身,就是其全部智慧的浓缩。Dan McKinley 警告我们,在启动一个新项目时,要警惕那些闪亮、前沿、充满炒作的新技术的诱惑。

  • 新技术:有未知的 Bug 和弱点,当你遇到问题时,社区可能还没有解决方案,你将孤立无援。
  • “无聊”的技术(如 Postgres, Java, Go):虽然有其自身的问题,但经过数十年(或多年)的实战检验,它们几乎所有可能遇到的问题,都有成熟的、有据可查的解决方案。

McKinley 提出了一个有趣的模型:每个公司都有三枚“创新代币” (innovation tokens)。如果你想在一个项目中使用一项未经充分验证的新技术,你就必须花掉一枚代币。请明智地使用它们。

Go 语言本身,在许多方面,已经成为了“无聊技术”的典范。它稳定、向后兼容、拥有强大的标准库和成熟的生态。当我们进行技术选型时,应该问自己:我们当前的核心问题,真的需要一个全新的、我们团队不熟悉的“闪亮新事物”来解决吗?还是说,用我们已经精通的“无聊”工具,就足以应对挑战?选择“无聊”,往往是通往项目成功最可靠的路径。

9. 我把自己锁在了数字生活之外

(“I’ve locked myself out of my digital life” by Terence Eden, 2022)

这篇文章以一个引人入胜的思想实验开场:如果一道闪电击中了你的房子,摧毁了你所有的电子设备,你将如何恢复你的数字生活?

作者 Terence Eden 意识到,尽管他有密码管理器、硬件密钥和多重备份,但所有这些安全措施的“入口”,都依赖于他手边的某个设备。如果所有设备同时被毁,他将无法访问密码管理器,也无法使用硬件密钥,从而陷入一个无法恢复的死循环。

这个故事迫使读者思考一个被我们常常忽略的问题:我们的灾难恢复计划,是否本身就依赖于那些可能会在灾难中一同消失的东西?

这篇文章的教训,超越了个人数字安全,直指系统设计的核心——韧性 (Resilience)避免单点故障

当我们设计一个分布式系统时,我们是否考虑过最坏的情况?

  • 我们的备份恢复流程,是否依赖于某个中心化的、可能会一同宕机的认证服务?
  • 我们的配置中心如果不可用,应用是否能以一种“降级”但仍可用的模式启动?
  • 在多云或混合云部署中,我们的跨区域故障转移方案,是否隐藏了对某个单一 DNS 提供商或证书颁发机构的隐式依赖?

Terence 的故事提醒我们,真正的系统韧性,不仅仅是拥有备份和冗余,更是要反复审视和测试我们的恢复路径,确保在极端情况下,我们不会发现自己“被锁在门外”。

10. Bonus:Brad Fitzpatrick 论输入验证的“咆哮”

(Brad Fitzpatrick on parsing user input, 2009)

最后,是一段来自 Go 社区大神、Memcached 和 LiveJournal 的创造者 Brad Fitzpatrick 的“咆哮”,这段话源于一本访谈录《Coders at Work》。当被问及软件工程的伦理时,他将矛头直指糟糕的输入验证:

“我希望每个人在他们的信用卡表单上都能保持一致,让我TMD能输入空格或连字符。计算机很擅长移除那些狗屎。别告诉我该如何格式化我的数字。”

这段充满激情的“粗口”,完美地概括了一个核心的用户体验原则:宽进严出 (Be liberal in what you accept, be conservative in what you produce)

作为 API 或 UI 的设计者,我们的责任是尽可能地减轻用户的负担。计算机是用来处理繁琐、重复性工作的。如果用户输入了一个带空格的电话号码,或者一个全角的逗号,我们的程序应该默默地、智能地将其清理和格式化,而不是粗暴地拒绝并抛出一个错误。

Fitzpatrick 的“咆哮”时刻提醒着我们:每一次当你设计一个输入字段时,都要站在用户的角度思考,并记住那句话——“计算机很擅长移除那些狗屎。”

小结:构建衡量“好”与“坏”的永恒坐标系

从 Joel Spolsky 对工程文化的拷问,到 Fred Brooks 对复杂性的深刻剖析;从 Alexis King 对类型安全的精妙论证,到 Dan McKinley 对技术选型的务实忠告…… 当我们跟随 Michael Lynch 的脚步,完成这次跨越四十年的思想巡礼后,我们收获的远不止是一份“书单”。

技术浪潮来了又去,今天我们手中的工具,明天可能就会过时。但这些围绕着“人”的根本原则——清晰性、简单性、健壮性、同理心、风险意识——却是永恒的。它们是区分一名普通的“代码实现者”与一位真正的“软件工程师”的分水岭。

这份清单,最终为我们构建的,是一个内心深处的、用以衡量“好”与“坏”的永恒坐标系。在未来的职业生涯中,无论面对何种炫目的新技术或棘手的工程问题,这个坐标系都将指引我们,做出更明智、更持久、也更具价值的决策。

资料链接:https://refactoringenglish.com/blog/software-essays-that-shaped-me


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

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

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

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

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


想系统学习Go,构建扎实的知识体系?

我的新书《Go语言第一课》是你的首选。源自2.4万人好评的极客时间专栏,内容全面升级,同步至Go 1.24。首发期有专属五折优惠,不到40元即可入手,扫码即可拥有这本300页的Go语言入门宝典,即刻开启你的Go语言高效学习之旅!


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

Go 1.25中值得关注的几个变化

本文永久链接 – https://tonybai.com/2025/08/15/some-changes-in-go-1-25

大家好,我是Tony Bai。

北京时间2025年8月13日,Go 团队如期发布了 Go 语言的最新大版本——Go 1.25。按照惯例,每次 Go 大版本发布时,我都会撰写一篇“Go 1.x 中值得关注的几个变化”的文章。自 2014 年的 Go 1.4 版本起,这一系列文章已经伴随大家走过了十一个年头。

不过,随着我在版本冻结前推出的“Go 1.x 新特性前瞻”系列,以及对该大版本可能加入特性的一些独立的解读文章,本系列文章的形式也在不断演变。本文将不再对每个特性进行细致入微的分析,因为这些深度内容大多已在之前的《Go 1.25 新特性前瞻》一文中详细讨论过。本文将更聚焦于提炼核心亮点,并分享一些我的思考。

好了,言归正传,我们来看看Go 1.25带来了哪些惊喜!

语言变化:兼容性基石上的精雕细琢

正如 Go 一贯所做的,新版 Go 1.25 继续遵循 Go1 的兼容性规范。最令 Gopher 们安心的一点是:Go 1.25 没有引入任何影响现有 Go 程序的语言级变更

There are no languages changes that affect Go programs in Go 1.25.

这种对稳定性的极致追求,是 Go 成为生产环境首选语言之一的重要原因。

尽管语法层面波澜不惊,但语言规范内部却进行了一次“大扫除”——移除了“core types”的概念。这一变化虽然对日常编码无直接影响,但它简化了语言规范,为未来泛型可能的演进铺平了道路,体现了 Go 团队在设计层面的严谨与远见。关于此变化的深度解读,可以回顾我之前的文章《Go 1.25 规范大扫除:移除“Core Types”,为更灵活的泛型铺路》。

编译器与运行时:看不见的性能飞跃

如果说 Go 1.24 的运行时核心是优化 map,那么 Go 1.25 的灵魂则在于让 Go 程序更“懂”其运行环境,并对 GC 进行了大刀阔斧的革新。

容器感知型 GOMAXPROCS

这无疑是 Go 1.25 最具影响力的变化之一。在容器化部署已成事实标准的今天,Go 1.25 的运行时终于具备了 cgroup 感知能力。在 Linux 系统上,它会默认根据容器的 CPU limit 来设置 GOMAXPROCS,并能动态适应 limit 的变化。

这意味着,只需升级到 Go 1.25,你的 Go 应用在 K8s 等环境中的 CPU 资源使用将变得更加智能和高效,告别了过去因 GOMAXPROCS 默认值不当而导致的资源浪费或性能瓶颈。更多细节,请参阅我的文章《Go 1.25 新提案:GOMAXPROCS 默认值将迎 Cgroup 感知能力,终结容器性能噩梦?》。

实验性的 Green Tea GC

Go 1.25 迈出了 GC 优化的重要一步,引入了一个新的实验性垃圾收集器。通过设置 GOEXPERIMENT=greenteagc 即可在构建时启用。

A new garbage collector is now available as an experiment. This garbage collector’s design improves the performance of marking and scanning small objects through better locality and CPU scalability.

据官方透露,这个新 GC 有望为真实世界的程序带来 10%—40% 的 GC 开销降低。知名go开发者Josh Baker(@tidwall)在Go 1.25发布正式版后,在X上分享了自己使用go 1.25新gc(绿茶)后的结果,他开源的实时地理空间和地理围栏项目tile38的GC开销下降35%:

这是一个巨大的性能红利,尤其对于重度依赖GC的内存密集型应用。虽然它仍在实验阶段,但其展现的潜力已足够令人兴奋。对 Green Tea GC 设计原理感兴趣的朋友,可以阅读我的文章《Go 新垃圾回收器登场:Green Tea GC 如何通过内存感知显著降低 CPU 开销?》。

此外,Go 1.25 还修复了一个存在于 Go 1.21 至 1.24 版本中可能导致 nil pointer 检查被错误延迟的编译器 bug,并默认启用了 DWARFv5 调试信息,进一步缩小了二进制文件体积并加快了链接速度,对DWARFv5感兴趣的小伙伴儿可以重温一下我之前的《Go 1.25链接器提速、执行文件瘦身:DWARF 5调试信息格式升级终落地》一文,了解详情。

工具链:效率与可靠性的双重提升

强大的工具链是 Go 生产力的核心保障。Go 1.25 在此基础上继续添砖加瓦。

go.mod 新增 ignore 指令

对于大型 Monorepo 项目,go.mod 新增的 ignore 指令是一个福音。它允许你指定 Go 命令在匹配包模式时应忽略的目录,从而在不影响模块依赖的前提下,有效提升大型、混合语言仓库中的构建与扫描效率。关于此特性的详细用法,请见《Go 工具链进化:go.mod 新增 ignore 指令,破解混合项目构建难题》。

支持仓库子目录作为模块根路径

一个长期困扰 Monorepo 管理者和自定义 vanity import 用户的难题在 Go 1.25 中也得到了解决。Go 命令现在支持在解析 go-import meta 标签时,通过新增的 subdir 字段,将 Git 仓库中的子目录指定为模块的根。

这意味着,你可以轻松地将 github.com/my-org/my-repo/foo/bar 目录映射为模块路径 my.domain/bar,而无需复杂的代理或目录结构调整。这个看似微小但备受期待的改进,极大地提升了 Go 模块在复杂项目结构中的灵活性。想了解其来龙去脉和具体配置方法,可以参考我的文章《千呼万唤始出来?Go 1.25解决Git仓库子目录作为模块根路径难题》。

go doc -http:即开即用的本地文档

这是一个虽小但美的改进。新的 go doc -http 选项可以快速启动一个本地文档服务器,并在浏览器中直接打开指定对象的文档。对于习惯于离线工作的开发者来说,这极大地提升了查阅文档的便捷性。详细介绍见《重拾精髓:go doc -http 让离线包文档浏览更便捷》。

go vet 新增分析器

go vet 变得更加智能,新增了两个实用的分析器:

  • waitgroup:检查 sync.WaitGroup.Add 的调用位置是否错误(例如在 goroutine 内部调用)。
  • hostport:诊断不兼容 IPv6 的地址拼接方式 fmt.Sprintf(“%s:%d”, host, port),并建议使用 net.JoinHostPort。

这些静态检查能帮助我们在编码阶段就扼杀掉一批常见的并发和网络编程错误。

标准库:功能毕业与实验探索

标准库的演进是每个 Go 版本的重要看点。

testing/synctest 正式毕业

在 Go 1.24 中以实验特性登场的 testing/synctest 包,在 Go 1.25 中正式毕业,成为标准库的一员。它为并发代码测试提供了前所未有的利器,通过虚拟化时间和调度,让编写可靠、无 flakiness 的并发测试成为可能。我曾撰写过一个征服 Go 并发测试的微专栏,系统地介绍了该包的设计与实践,欢迎大家订阅学习。

encoding/json/v2 开启实验

这是 Go 1.25 最受关注的实验性特性之一!通过 GOEXPERIMENT=jsonv2 环境变量,我们可以启用一个全新的、高性能的 JSON 实现。

Go 1.25 includes a new, experimental JSON implementation… The new implementation performs substantially better than the existing one under many scenarios.

根据官方说明,json/v2 在解码性能上相较于 v1 有了“巨大”的提升。这是 Go 社区多年来对 encoding/json 包性能诟病的一次正面回应。虽然其 API 仍在演进中,但它预示着 Go 的 JSON 处理能力未来将达到新的高度。对 v2 的初探,可以参考我的文章《手把手带你玩转 GOEXPERIMENT=jsonv2:Go 下一代 JSON 库初探》。jsonv2支持真流式编解码的方法,也可以参考《Go json/v2实战:告别内存爆炸,掌握真流式Marshal和Unmarshal》这篇文章。

sync.WaitGroup.Go:并发模式更便捷

Go 语言的并发编程哲学之一就是让事情保持简单。Go 1.25 在 sync.WaitGroup 上新增的 Go 方法,正是这一哲学的体现。

这个新方法旨在消除 wg.Add(1) 和 defer wg.Done() 这一对经典的样板代码。现在,你可以直接调用 wg.Go(func() { … }) 来启动一个被 WaitGroup 追踪的 goroutine,Add 和 Done 的调用由 Go 方法在内部自动处理。这不仅让代码更简洁,也从根本上避免了因忘记调用 Add 或 Done 而导致的常见并发错误。

关于这个便捷方法的来龙去脉和设计思考,可以回顾我之前的文章《WaitGroup.Go 要来了?Go 官方提案或让你告别 Add 和 Done 样板代码》。

其他:Trace Flight Recorder

最后,我想特别提一下 runtime/trace 包新增的 Flight Recorder API。传统的运行时 trace 功能强大但开销巨大,不适合在生产环境中持续开启。

trace.FlightRecorder 提供了一种轻量级的解决方案:它将 trace 数据持续记录到一个内存中的环形缓冲区。当程序中发生某个重要事件(如一次罕见的错误)时,我们可以调用 FlightRecorder.WriteTo 将最近一段时间的 trace 数据快照保存到文件。这种“事后捕获”的模式,使得在生产环境中调试偶发、疑难的性能或调度问题成为可能,是 Go 诊断能力的一次重大升级。更多详情可以参阅《Go pprof 迎来重大革新:v2 提案详解,告别默认注册,拥抱飞行记录器》。

小结

Go 1.25 的发布,再次彰显了 Go 语言务实求进的核心哲学。它没有追求华而不实的语法糖,而是将精力聚焦于那些能为广大开发者带来“无形收益”的领域:更智能的运行时、更快的 GC、更可靠的编译器、更高效的工具链

这些看似底层的改进,正是 Go 作为一门“生产力语言”的价值所在。它让开发者可以专注于业务逻辑,而将复杂的系统优化和环境适配,放心地交给 Go 语言自身。

我鼓励大家尽快将 Go 1.25 应用到自己的项目中,亲自感受这些变化带来的提升。Go 的旅程,仍在继续,让我们共同期待它在未来创造更多的可能。

感谢阅读!

如果这篇文章让你对 Go 1.25 新特性有了新的认识,请帮忙 点赞分享,让更多朋友一起学习和进步!


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

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

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

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

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


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

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! 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