标签 Rust 下的文章

Go 错误处理语法之争尘埃落定?Go 团队为何十五年探索后仍选择“不”

本文永久链接 – https://tonybai.com/2025/06/04/error-syntax

大家好,我是Tony Bai。

长久以来,Go 语言中 if err != nil 的错误处理模式因其普遍性和由此带来的代码冗余,一直是社区反馈中最持久、最突出的痛点之一。尽管 Go 团队及社区投入了大量精力,历经近十五年的探索,提出了包括 check/handle、try 内建函数以及借鉴 Rust 的 ? 操作符在内的多种方案,但始终未能就新的错误处理语法达成广泛共识。近日,Go 官方团队通过一篇博文正式阐述了其最新立场在可预见的未来,将停止寻求通过改变语法来简化错误处理,并将关闭所有相关的提案。 这一决策无疑在 Go 社区引发了广泛关注和深入思考。

漫漫探索路:从 check/handle 到 ? 操作符

Go 语言的错误处理冗余问题,尤其在涉及大量 API 调用且错误处理逻辑相对简单的场景下尤为突出。一个典型的例子如下:

func printSum(a, b string) error {
    x, err := strconv.Atoi(a)
    if err != nil {
        return err // 样板代码
    }
    y, err := strconv.Atoi(b)
    if err != nil {
        return err // 样板代码
    }
    fmt.Println("result:", x + y)
    return nil
}

在这个函数中,近一半的代码行用于错误检查和返回,这无疑增加了代码的视觉噪音,降低了核心逻辑的清晰度。因此,多年来,改进错误处理的呼声在 Go 开发者年度调查中一直居高不下。

Go 团队对此高度重视,并进行了一系列尝试:

check/handle 机制 (2018年)

由 Russ Cox 正式提出,基于 Marcel van Lohuizen 的草案设计。该机制引入了 check 用于检查错误并提前返回,handle 用于定义错误处理逻辑。

// 设想的 check/handle 用法
func printSum(a, b string) error {
    handle err { return err } // 定义错误处理
    x := check strconv.Atoi(a) // 检查错误
    y := check strconv.Atoi(b) // 检查错误
    fmt.Println("result:", x + y)
    return nil
}

然而,该方案因其复杂性未被广泛接受。

try 内建函数 (2019年)

作为 check/handle 的简化版,try 函数会在遇到错误时从其所在的封闭函数返回。

// 设想的 try 用法
func printSum(a, b string) error {
    x := try(strconv.Atoi(a))
    y := try(strconv.Atoi(b))
    fmt.Println("result:", x + y)
    return nil
}

尽管 Go 团队投入巨大,但 try 因其隐式的控制流改变(可能从深层嵌套表达式中返回)而遭到许多开发者的反对,最终也被放弃。Go 团队反思,或许引入新关键字并限制 try 的使用范围会是更好的路径。

借鉴 Rust 的 ? 操作符 (2024年)

由 Ian Lance Taylor 提出,希望通过借鉴其他语言中已验证的机制来取得突破。

// 设想的 ? 操作符用法
func printSum(a, b string) error {
    x := strconv.Atoi(a) ?
    y := strconv.Atoi(b) ?
    fmt.Println("result:", x + y)
    return nil
}

此方案虽然在小范围用户研究中表现出一定的直观性,但在社区讨论中依然未能形成足够支持,并引发了大量关于细节调整的建议。

除了官方提案,社区也贡献了数以百计的错误处理改进方案,但无一例外都未能获得压倒性的支持。

官方立场:为何按下暂停键?

面对多年探索未果的局面,Go 团队基于以下几点理由,做出了暂停错误处理语法层面改进的决定。

缺乏社区共识

这是最核心的原因。根据 Go 的提案流程,一项提案需要得到社区的普遍共识才能被接受。然而,在错误处理语法这个问题上,无论是官方还是社区的提案,都未能凝聚起足够的共识。甚至 Go 团队内部也未能就最佳方案达成一致。

维护现状的合理性

  • 时机问题: Go 已经发展了十五年,现有的错误处理方式虽然冗余,但功能完善且被广泛理解和使用。早期引入语法糖可能更容易被接受,但现在改变的门槛更高。
  • 避免制造新的“不快乐”: 即使找到了“完美”方案,强制推广新语法也可能让习惯了现有方式的开发者感到不适,重蹈类似泛型引入初期的一些争议。但与泛型不同,错误处理语法几乎会影响所有开发者。
  • Go 的设计哲学: Go 倾向于“只提供一种(或尽可能少)的方式来做同一件事”。引入新的错误处理语法会打破这一原则。有趣的是,:= 短变量声明中的变量重声明规则,最初也是为了解决连续错误检查中 err 变量命名问题而引入的,如果早期有更好的错误处理语法,这个规则或许就不需要了。

关注错误处理的本质,而非仅仅语法

func printSum(a, b string) error {
    x, err := strconv.Atoi(a)
    if err != nil {
        return fmt.Errorf("invalid integer: %q", a) // 附加信息
    }
    // ...
    return nil
}

在这种情况下,if err != nil 的样板代码占比相对减小。

  • 标准库的增强: 新的库函数(如 cmp.Or)或未来的库特性,可以在不改变语法的情况下帮助减少错误处理的样板代码。
func printSum(a, b string) error {
    x, err1 := strconv.Atoi(a)
    y, err2 := strconv.Atoi(b)
    if err := cmp.Or(err1, err2); err != nil { // 使用 cmp.Or
        return err
    }
    fmt.Println("result:", x+y)
    return nil
}

工具的辅助作用

  • 编写时: 现代 IDE(包括基于 LLM 的工具)已经能够很好地辅助生成重复的错误检查代码。
  • 阅读时: IDE 或可提供隐藏/折叠错误处理代码块的功能,减少视觉干扰。
  • 调试时: 显式的 if 语句更便于设置断点和添加调试输出,而高度集成的语法糖可能会使调试变得复杂。

语言演进的成本与优先级

  • 任何语言的改动都伴随着巨大的成本:设计、实现、文档更新、工具调整以及社区的适应。Go 团队规模有限,需要优先处理其他重要事项。
  • 开发者习惯的演变: 许多有经验的 Go 开发者表示,随着对 Go 错误处理哲学的深入理解和实践,最初感到的冗余问题会逐渐减轻。

对开发者的影响与未来展望

Go 团队的这一决定,意味着在可预见的未来,if err != nil 仍将是 Go 语言错误处理的标准范式。开发者需要:

  • 接受现状并深入理解其哲学: Rob Pike 的名言“Errors are values”依然是理解 Go 错误处理的核心。错误是程序正常流程的一部分,显式处理它们有助于编写健壮的软件。
  • 利用现有工具和库:
    • 善用 IDE 的代码生成和辅助功能。
    • 探索和使用标准库或第三方库提供的错误处理辅助工具(如 errors.Is, errors.As, fmt.Errorf 的 %w 以及可能的新库特性)。
  • 关注代码质量而非单纯追求简洁: 在需要详细错误上下文的地方,不要吝啬代码。清晰、可追溯的错误比极度简化的语法糖更有价值。
  • 代码可读性依然重要: 尽管语法层面不再追求极致简洁,但在错误处理逻辑本身,依然要力求清晰、易懂。

Go 团队也指出,他们并未完全关闭对错误处理改进的大门,只是将焦点从“语法层面”移开。未来可能会更深入地研究错误处理的本质问题,例如如何更好地构造和传递包含丰富上下文的错误信息,以及通过库而非语法来提供更好的支持。

小结

Go 语言在错误处理语法上的探索历程,充分体现了其在语言设计上的审慎与对社区反馈的重视。尽管长达十五年的努力未能催生出被广泛接受的新语法,但这并不代表失败,而是对 Go 核心设计原则的坚守和对现实复杂性的认知。

对开发者而言,这意味着需要继续在现有的、经过验证的错误处理模式下精进技艺,同时期待 Go 语言在库和工具层面带来更多辅助,以更优雅、更高效地构建可靠的应用程序。

这场关于错误处理的“语法之争”虽然暂时告一段落,但其引发的关于简洁、清晰、实用与语言稳定性的思考,将对 Go 的长远发展产生深远影响。


对于 Go 官方在错误处理语法上的最新立场,您有什么看法?您认为现有的 if err != nil 模式在您的日常开发中体验如何?欢迎在评论区分享您的观点和实践经验!

想要更深入地掌握 Go 语言的错误处理哲学、高级技巧以及更多进阶主题吗?欢迎订阅我的《Go语言进阶课》专栏,与我们一同探索 Go 的魅力,提升您的 Go 开发技能!


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

AI 编码工具“真香”还是“智商税”?一位资深码农的“挑衅”与Go开发者的反思

本文永久链接 – https://tonybai.com/2025/06/03/provocation-about-ai-assisted-programming

大家好,我是Tony Bai。

最近,fly.io 博客上该公司开发者 Thomas Ptacek 的一篇题为《My AI Skeptic Friends Are All Nuts》的文章,在开发者社区掀起了不小的波澜,一度登顶HN。Ptacek 以一位自称“严肃开发者”(从C语言到Go、Rust均有涉猎)的口吻,向那些对 AI 辅助编程持怀疑态度的“聪明朋友们”发出了略带“挑衅”的宣言:“即使 LLM 今天停止所有进展,它仍然是我职业生涯中发生的第二重要的事情”

这篇文章的观点之鲜明、论证之犀利,让我印象深刻。恰逢 前期Google I/O 2025 大会再次展示了 Gemini 等 AI 模型在编码领域的惊人进展,我们不禁要问:AI 编码工具,究竟是能极大提升生产力的“真香”利器,还是又一轮被过度炒作的“智商税”?作为开发者,特别是 Gopher,我们又该如何看待和应对这场正在发生的变革?

在这篇文章中,我就和大家一起来看看 Thomas Ptacek 对AI辅助编程演进的犀利观点以及他的反思。看看你是否认同他的想法。

误区澄清:现代 AI 辅助编程早已不是“复制粘贴”

Ptacek 在文章开篇就点出了一个关键问题:很多人对 AI 辅助编程的印象,还停留在半年前甚至两年前的水平。他写道:“如果你在6个月前(或者,天哪,两年前用Copilot的时候)尝试使用LLM编码并失败了,那么你并没有在做大多数严肃的LLM辅助编码者正在做的事情”。

那么,现在“严肃的LLM辅助编码者”在做什么呢?Ptacek 强调,他们使用的是 Agent (智能体)。这些 AI Agent 不再仅仅是根据提示生成代码片段让你复制粘贴,它们能够:

  • 自主地在你的代码库中进行探索。
  • 直接创建和修改文件。
  • 运行各种工具, 如编译器、测试框架、linter、formatter 等。
  • 与 Git 等版本控制系统交互。
  • 根据编译和测试结果进行迭代和修正。
  • 通过 MCP 或类似机制调用你设置的任意工具。

Ptacek强调:如果你对 AI 编码的印象还停留在 ChatGPT 网页上简单问答然后手动复制代码,那么你可能真的低估了当前 AI Agent 所能达到的自动化和智能化水平。

AI Agent 如何提升编码效率?Ptacek 的“积极案例”

Ptacek 认为,LLM(通过 Agent)能够极大地提升编码效率,主要体现在以下几个方面:

  1. 处理“乏味代码”: LLM 可以编写你需要编写的大部分乏味代码。而大多数项目中的大多数代码都是乏味的。这能让开发者从重复性的工作中解放出来,更快地进入“调整代码并立即看到效果更好”的“黄金时刻 (golden moment)”,获得即时反馈的“多巴胺冲击”。

  2. 克服项目启动的“惯性”: 面对一个新项目,繁琐的初始设置、依赖管理、基础架构搭建等往往令人望而却步。LLM Agent 可以被指示去“搞定这些破事,直接将你带到“事情几乎可以工作”的阶段。

  3. 自动化“苦差事”: 那些你不想做但又必须做的“脏活累活”,比如大规模的单元测试重构,完全可以交给 AI Agent 在虚拟机里折腾几个小时,然后带着一个 PR 回来。这反而会“逼迫”你去做“真正的工作 (real work)”。

回应常见的质疑:Ptacek 的“辩护”

Ptacek 在文章中也针对开发者对 AI 编码的常见质疑进行了犀利的回击,这些回应也为我们思考 Go 语言在 AI 时代的定位提供了新的视角。

  • 关于代码质量与审查责任——“你根本不知道它写的是什么!”

Ptacek强调,开发者始终对合并到 main 分支的代码负责,无论是否使用 LLM。 LLM 生成的代码是“可知的”,你需要阅读它,甚至花时间将其调整为你自己的风格。如果连 LLM 生成的“乏味、重复”的代码都难以理解和消化,那可能是开发人员的“技能问题”。

  • 关于“幻觉 (hallucination)”问题——“它会编造不存在的API!”

Ptacek 认为,对于编程而言,Agent 通过工具链(linting、编译、运行测试)形成的闭环反馈,已经(或多或少地)解决了“幻觉”问题。“如果它们的LLM编造了一个新的函数签名,Agent会看到错误。它们将其反馈给LLM,LLM会说‘哦,是的,我完全是编造的’,然后重试”。这里不能不提到** Go 语言的快速编译特性,使得这种“试错-反馈-修正”的闭环能够非常高效地运转。同时,Go 强大的标准库和清晰的 API 设计,是否也能减少 LLM“编造”API 的概率,或者使其更容易被工具链检测出来。

  • 关于“代码像初级开发者写的”——“质量太差!”

Ptacek 回应:“一个实习生一个月要花20美元吗?因为 Cursor.ai 就是这个价钱”。他认为,高级开发者的职责之一就是让能力稍逊的编码者(无论是人类还是“智能体”)变得高效。使用好 Agent 本身就是一项技能和一项涉及提示、索引和(尤其是)工具链的工程项目。 LLM 只有在你允许的情况下才会产生劣质代码。

  • 关于“不擅长特定语言 (如 Rust)”——“它写不了我的 Rust!”

Ptacek 认为这更多是语言生态和工具链成熟度的问题,而非 LLM 能力的根本缺陷。他特别指出:“我主要用 Go 工作……Go 恰到好处的类型安全、广泛的标准库以及推崇(通常是重复性)惯用法的文化。LLM 在生成 Go 代码方面表现出色。” 想必很多Go开发者也有着与Ptacek相同的感受,这是 Go 语言在 AI 辅助编程时代的一个显著优势! Go 的简洁性、明确性、强大的标准库覆盖、以及社区对代码规范和惯用法的重视(例如 Effective Go),使得 Go 代码的模式相对统一和可预测,这为 LLM 的学习和生成提供了极大的便利。

对“手工艺精神”与“平庸代码”的再思考

Ptacek 对软件开发中的“手工艺精神”和对“平庸代码”的过度排斥也提出了批判。

  • 他认为:专业软件开发者的工作是用代码为人们解决实际问题。在日常工作中,我们不是工匠。过度追求代码的“优雅”而忽视实际产出,可能是“自我安慰的yak-shaving(指做无关紧要的琐事)”。

  • 对于“平庸代码”,他认为:开发者都喜欢对代码自吹自擂。他们担心LLM降低了质量的“天花板”。也许吧。但它们也提高了“地板”。LLM 生成的“平庸但彻底”的代码,可能比人类开发者“抖机灵”但引入缺陷的代码更有价值。

这也引发我们思考:在追求卓越工程的同时,我们是否也应该更务实地看待不同场景下对代码质量的不同要求?LLM 是否能帮助我们更高效地处理那些“允许平庸”但又耗时耗力的部分,从而让我们能将精力投入到真正需要人类智慧和创造力的核心工作中?

Go 开发者如何拥抱 AI Agent 的时代?

Ptacek 的文章,无论你是否完全认同其所有观点,都为我们描绘了一个 AI Agent 深度参与软件开发的未来图景。作为 Gopher,我们应该如何应对?

  1. 更新认知,拥抱变化: 首先要认识到,现代 AI 辅助编程已经远超简单的代码补全。应该主动去了解和体验基于 Agent 的编码工具。
  2. 学习与 AI Agent 高效协作: 掌握提示工程技巧,学会如何清晰地向 Agent表达需求、提供上下文、引导其生成和修改代码。
  3. 发挥 Go 语言的优势: 利用 Go 的简洁性、强大的标准库、快速的编译和测试工具链,为 AI Agent 构建高效的开发和反馈环境。思考如何让 Go 代码对 AI 更“友好”。
  4. 提升自身的核心价值: 将精力更多地投入到 AI 难以替代的领域:复杂系统设计、架构决策、需求理解与抽象、创新思维、以及对 Go 底层原理和并发模型的深刻理解。
  5. 参与构建 Go 的 AI Agent 生态: Go 语言本身非常适合构建 CLI 工具和后端服务。我们是否可以利用 Go 来创建更强大的、针对 Go 开发的 Agent 辅助工具或平台?

小结:保持开放,主动实践,与 AI 共舞

AI 编码工具究竟是“真香”还是“智商税”?或许答案因人而异,也因我们如何使用它而异。但 Thomas Ptacek 的“挑衅”至少提醒我们,不能用静止的眼光看待飞速发展的技术。

AI 辅助编程的浪潮已然到来。对于我们 Gopher 而言,Go 语言的特性使其在这波浪潮中具有独特的优势。与其固守过去的经验和偏见,不如保持开放的心态,主动去实践和探索,让 AI Agent 成为我们提升自身能力、加速项目交付、并最终能专注于更有创造性工作的强大伙伴。

毕竟,正如 Ptacek 所说,当他那些“聪明的怀疑论朋友们”最终接受并开始使用这些工具时,他们将会让编码 Agent 比今天强大得多。

而我们,又怎能置身事外呢?


聊一聊,也帮个忙:

  • 你目前在工作中使用 AI 辅助编程工具(如 Copilot, Cursor.ai, Gemini Code Assist,Trae等)的体验如何?它在哪些方面帮助了你,又有哪些不足?
  • Ptacek 文章中对 AI 编码的哪个观点让你印象最深刻?你同意还是反对?为什么?
  • 你认为 Go 语言在 AI 辅助编程时代,还有哪些可以进一步优化的方向,以更好地与 LLM Agent 结合?

欢迎在评论区留下你的思考和经验。如果你觉得这篇文章提供了一个值得探讨的视角,也请转发给你身边的开发者朋友们,一起参与这场关于 AI 与编程未来的讨论!

想与我进行更深入的 Go 语言、AI 赋能开发与技术趋势交流吗? 欢迎加入我的“Go & AI 精进营”知识星球

img{512x368}

我们星球见!


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

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