Logo

site iconTonyBai | 白明

重复
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

TonyBai | 白明 RSS 预览

Go 的“最小惊讶原则”破功了吗?—— 一个vet 新提案引发的思考

2025-12-09 16:26:06

本文永久链接 – https://tonybai.com/2025/12/09/vet-add-check-for-using-verb-q

大家好,我是Tony Bai。

Go 语言的设计哲学,一向以“简单、明确、无魔法”著称,其目标是让代码的行为尽可能符合开发者的直觉,即遵循所谓的“最小惊讶原则” (Principle of Least Astonishment)。然而,最近一个被 Go 团队接受的 go vet 新提案(NO.72850),却像一面镜子,映照出了 Go 在这条道路上的一些“盲区”。

这个提案本身很简单,但它所揭示的问题却非常深刻:当一个开发者写下 fmt.Printf(“%q”, 123) 时,他期望得到的是字符串 “123″,但实际得到的却是 ‘{\n’。这种期望与现实的巨大鸿沟,让我们不得不反思:Go 的设计,真的总是那么“不言自明”吗?

问题的核心:%q 与 string(i) 的“历史包袱”

该提案的核心,是要求 go vet 工具对 fmt.Printf 中 %q 动词的误用发出警告。%q 的文档清晰地说明,它的作用是“将一个字符字符串,格式化为一个带单引号或双引号、经过 Go 语法安全转义的字面量”。

然而,许多开发者会想当然地认为,%q 能够像 %v 或 %d 一样,处理普通的整数。这种误解导致了令人惊讶的结果:

package main

import "fmt"

func main() {
    num := 123

    // 开发者期望: "123"
    // 实际输出: '{'
    // 为什么?因为 123 是字符 '{' 的 ASCII/Unicode 码点。
    fmt.Printf("fmt.Printf(\"%%q\", 123) -> %q\n", num)
}

输出:

fmt.Printf("%q", 123) -> '{'

这个行为,与另一个 Go 新手常见的陷阱如出一辙——string(i) 整数到字符串的转换

func main() {
    num := 123

    // 开发者期望: "123"
    // 实际输出: "{"
    // 为什么?因为 string(i) 的作用是将一个 Unicode 码点转换为其对应的 UTF-8 字符串。
    fmt.Printf("string(123) -> %s\n", string(num))
}

输出:

./prog.go:11:36: conversion from int to string yields a string of one rune, not a string of digits

Go vet failed.

string(123) -> {

这两个例子共同揭示了一个问题:Go 在处理“数字”与“字符”的转换时,其行为源自 C 语言的悠久传统,但对于没有这种历史背景的现代开发者而言,这无疑是“反直觉”的。正确的做法,本应是使用 strconv.Itoa(123)。

go vet:是“创可贴”还是“守护神”?

Go 团队接受了这个提案,意味着未来的 go vet 将会像它已经对 string(i) 做的那样,对 fmt.Printf(“%q”, non_char_int) 这样的代码发出警告。

这引出了一个更深层次的讨论:我们是在用 vet 工具,为语言设计上的“瑕疵”打补丁吗?

  • 一方观点:如果一个 API 如此容易被误用,以至于需要一个外部工具来纠正它,那么这个 API 本身的设计可能就存在问题。像 printf 这种继承自 C 语言的、依赖于“格式化字符串”与可变参数类型匹配的范式,本身就是类型不安全的,难以做到“无需文档即可正确使用”。

  • 另一方观点(务实派):Go 的设计,是在表达力、性能和历史兼容性之间做出的权衡。string(i) 的行为对于处理 rune 和 byte 极其高效和方便,为了这个核心用例,牺牲一些对普通 int 的“直觉性”是值得的。printf 家族虽然有其历史包袱,但其功能强大且广为人知。

在这种权衡之下,go vet 扮演的角色,就不仅仅是一个“创可贴”,而更像是一个“守护神”。它成为了 Go 语言设计哲学的一部分,代表了一种务实的工程决策

语言本身保持小巧和高性能,而将那些复杂的、易出错的模式检查,交给一个同样作为一等公民的、可不断演进的静态分析工具链。

一个惊人的发现:%q 误用有多普遍?

为了评估这个提案的影响,Go 团队成员 Alan Donovan 对约 10,000 个开源 Go 模块进行了扫描,结果令人震惊:

  • 共发现了 42,976 处 fmt.Printf(“%q”, …) 的潜在误用!

他随机抽查了其中的几十个案例,发现几乎全是“真阳性”——开发者显然是想用 %q 来打印一个带引号的数字或普通变量,却意外地打印出了一个不相关的 Unicode 字符。

这个数据雄辩地证明,%q 的“反直觉”行为,并非个别新手的困惑,而是一个在 Go 社区中普遍存在的认知盲区。这也使得为 go vet 增加这个检查的必要性,变得无可辩驳。

小结:在“简单”与“清晰”之间求索

%q 的故事,是 Go 语言设计哲学复杂性的一次精彩展现。它告诉我们,“简单”并非一个单薄的概念。

  • string(i) 的设计,对于语言实现和 rune 处理来说,是简单的
  • fmt.Printf 的格式化动词,对于熟悉 C 传统的人来说,是简单的

但当这些“局部简单”的特性,组合在一起并呈现给一位来自不同背景的开发者时,其行为就可能不再清晰 (Clear),甚至变得“令人惊讶”。

Go 语言通过不断地为其守护神——go vet 工具——添加新的“神力”,来弥合“简单”与“清晰”之间的鸿沟。这正是Go团队承认历史,正视现实,并用工程化的手段,引导开发者走向更健壮、更正确的代码的一种务实策略。

下一次,当 go vet 在你的代码下划出波浪线时,或许你看到的,将不再是一个冰冷的警告,而是一份来自 Go 设计者们的、穿越时空的“温馨提示”。

资料链接:https://github.com/golang/go/issues/72850


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

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

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

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

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


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

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


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

© 2025, bigwhite. 版权所有.

给了机关枪,你却非要耍大刀:2025 年末,程序员 All in AI 的生存启示录

2025-12-09 08:17:51

本文永久链接 – https://tonybai.com/2025/12/09/programmer-all-in-ai-survival-revelation-in-2025

大家好,我是Tony Bai。

最近逛 Twitter 和技术论坛,我发现了一个非常有意思,甚至有些魔幻的现象。

尽管我们已经站在了 2025 年末,距离 ChatGPT 震撼发布已经过去了整整三年,AI 能力早已从“玩具”进化成了“重型武器”。但在评论区里,依然充斥着大量这样的声音:

  • “真程序员谁用 AI 啊,那都是给脚本小子用的。”
  • “用 AI 生成代码没有灵魂,我还是习惯自己掌控每一个字符。”
  • … …

看着这些言论,再联想到身边团队和朋友圈中的一些类似的现象,我忍不住在我的知识星球中发了一句感慨:

“给了你机关枪,你却非得用大刀。这不仅是不合时宜,简直是暴殄天物”

这三年,AI 不再是那个只会写打油诗的聊天机器人,它是基建,是水电,是程序员的第二大脑。

在这个时间节点,命题早已改变:不再是“要不要用 AI”,而是“你为什么还在用大刀砍柴?”

但在真正 All in AI 之前,我们必须先看清现实中普遍存在的“四大怪象”,并一一打破它们。


现实中的“四大怪象”

如果你仔细观察身边的技术团队,朋友圈或者审视一下自己,可能就会发现我们都在不自觉地陷入以下误区:

怪象一:技术洁癖引发的“伪精英心态”

很多人认为依赖工具是能力退化的表现。他们以“纯手工打造”为荣,认为只有自己敲出来的代码/文字才叫硬核,用 AI 就像是“作弊”。

怪象二:工具依赖导致的“思维躺平”

另一极端是,有了 AI 就不思考了。遇到问题直接扔给 AI,AI 给什么就用什么,不再去探究底层的原理,甚至觉得“反正 AI 会,我不用学了”。

怪象三:盲目信任带来的“埋雷行为”

把 AI 当作真理的化身。直接 Copy & Paste AI 生成的代码上线,不看逻辑,不测边界,结果把 AI 的幻觉(Hallucination)直接变成了线上的 Bug。

怪象四:浅尝辄止的“低效勤奋”

虽然也在用 AI,但只停留在“帮我写个正则”、“解释这段代码”的浅层阶段。手里拿着加特林机关枪,却只把它当烧火棍用。


All in AI 之前的“四重认知突围”

针对上述怪象,如果想在 2025 年以及未来几年生存并晋级,我们需要进行一次彻底的认知重构。

认知 1:拒绝羞耻感 —— 它是“外骨骼”,不是“轮椅”

(对标怪象一)

越是基本功扎实的老兵,越容易有“技术羞耻感”。请立刻抛弃这种旧思维。

在 2025 年,能力定义的公式变了

  • 旧能力 = 记忆力 + 手速 + 经验
  • 新能力 = (经验 + 洞察) × AI 算力

使用 AI 不是因为你“能力不行”需要轮椅,而是为了放大你的能力。它让你从繁琐的语法/文书细节(Syntax)中解脱出来,让你的架构设计能力得以十倍级释放。善用“机关枪”是特种兵的素养,不是逃兵的借口。

认知 2:拒绝躺平 —— 是“升维”,不是“减负”

(对标怪象二)

以为用了 AI 就可以不学习了?大错特错。

AI 时代的学习逻辑发生了倒置: AI 负责“已知知识的检索与生成”,你负责“未知领域的洞察与判断”。

当 AI 帮你搞定了 80% 的“实现细节(How)”,你必须把节省下来的精力,投入到那 20% 更核心的“价值判断(Why & What)”中。

你不仅不能停止学习,反而要学得更深、更广——否则你甚至不知道该如何向 AI 提问,更不知道如何判断它给出的方案是平庸还是卓越。

认知 3:坚守底线 —— 做“机长”,不做“乘客”

(对标怪象三)

AI 的第一性原理(概率预测)决定了它永远存在“一本正经胡说八道”的可能。

对 AI 输出的成果物进行严苛的审核 (Review),是任何成果物发布前的必经路径。

你需要从“Writer(撰稿人)”转型为“Editor-in-Chief(总编辑)”

你是机长,AI 是副驾驶。它负责操作仪表盘,但你负责决定航向,并对每一次降落的安全性负责。 没有审核的 AI 代码/文档,就是一颗定时炸弹。这意味着你不能只看代码跑通了没有,还要像审查实习生代码一样,去盘问它的逻辑漏洞和边缘情况。

认知 4:直面竞争 —— 比的是“枪法”,不是“有枪”

(对标怪象四)

三年过去,AI 已经祛魅。现在人人手里都有一把“机关枪”(Cursor, Claude Code, Copilot 等)。

竞争的维度变了:不再是谁有枪(因为大家都有),而是谁的枪法更准。

  • 初级枪法: 单轮对话,只会问简单问题。
  • 高级枪法: 懂得 Context Injection(上下文注入)、Chain of Thought(思维链)、Spec-Driven(规范驱动开发工作流)。

“都用 AI”只是入场券。 真正的比拼,在于谁用得更深、更精,谁能用这把枪打出“百步穿杨”的效果。


小结:是时候All in AI了!

技术历史的车轮滚滚向前,残酷性从未改变。

每一次技术范式的转移,都会留下一批抱残守缺的“大刀队”。他们不是不努力,他们甚至比谁都辛苦,每天挥舞大刀砍得汗流浃背,但在“机关枪”的扫射下,这种努力显得苍白无力。

2025 年末,放下你的大刀吧。

去学习怎么校准瞄准镜,怎么控制后坐力,怎么设计交叉火力网。这不丢人。这才是对技术、对自己职业生涯最大的尊重。


互动话题

在使用 AI 编程的过程中,你遇到过最让你“细思极恐”的时刻是什么?或者最让你感到“真香”的瞬间是什么?欢迎在留言区分享你的故事。


如何练就“百步穿杨”的枪法?

文章里我们说了,“都用 AI”只是入场券,真正的决胜点在于谁用得更深、更精,谁拥有一套高维度的“AI 原生工作流”

如果你已经决定放下“大刀”,拿起“机关枪”,但面对市面上眼花缭乱的工具(Claude Code, Cursor, Windsurf)和碎片化的技巧,感到无从下手;

或者你虽然用了 AI,但发现自己依然陷入在“改 Bug -> AI 生成新 Bug”的低效死循环中;

那么,欢迎加入我的极客时间专栏《AI 原生开发工作流实战》

在这里,我们将深入实战:

  • 重构开发范式: 彻底告别“聊天式编程”,掌握 SDD (规范驱动开发) 的核心心法,学会用 Spec 文档精准指挥 AI。
  • 驾驭 Agentic 系统: 深入剖析 Claude Code 等 Agentic Tools 的底层逻辑,把它们变成你忠实的“外包团队”。
  • 构建私有/团队工作流: 手把手教你搭建一套“人脑定义目标 + AI 并发执行”的高效流水线。

别让手里的机关枪生锈。 点击下方卡片,我们一起在实战中进化。


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

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

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

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

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


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

© 2025, bigwhite. 版权所有.

拒绝“面条代码”,做有架构思维的 Go API 设计师

2025-12-08 07:46:28

本文永久链接 – https://tonybai.com/2025/12/08/api-design-pattern-and-implementation

大家好,我是Tony Bai。

在 Go 语言的圈子里摸爬滚打这么多年,我经常被问到这样一个问题:

“Tony,我已经熟悉了 Go 的语法,也会用 Gin 写增删改查(CRUD)了,为什么我写的 API 还是经常被前端吐槽?为什么业务逻辑稍微一变,我的代码就要推倒重来?为什么我的接口文档和代码永远对不上?”

这并不是你一个人的困惑。在多年的一线架构与咨询工作中,我见过太多 “能跑但不可维护” 的 API 系统:

  • 命名随心所欲:同一个系统里,获取用户有时候叫 /get_user,有时候叫 /user/query,动词名词混用,仿佛是不同的人在堆砌代码。
  • 返回格式像盲盒:报错时有时候返回 HTTP 400,有时候返回 200 并在 Body 里写个 “code”: -1,前端解析代码写得苦不堪言。
  • 性能与扩展性的噩梦:为了查一个字段,返回了整个数据库表的所有列;为了加一个新功能,不得不强迫所有老版本的 App 强制更新。

这就是典型的“面条代码”(Spaghetti Code)。

在软件工程中,它通常指代那些控制流复杂、逻辑纠缠不清的代码。而在 API 设计领域,它特指那些缺乏统一结构、动词名词混用、层级关系混乱的接口定义。它们就像一碗煮烂的面条,虽然勉强能吃(代码能跑通),但你永远理不清哪根是哪根(无法维护与扩展)。

这些问题的根源,不在于你对 Go 语言掌握得不够熟练,也不在于 Gin 等Web开发框架本身,而在于缺乏“API 架构设计”的系统性思维

写代码只是最后一步,设计才是灵魂

为什么我们需要“设计”API?

在云原生时代,API 就是系统之间的“契约”。如果契约设计得随意、混乱,那么微服务之间的交互就会变成一场灾难。

很多开发者认为,写 API 不就是“接收请求 -> 查数据库 -> 返回 JSON”吗?但这只是实现(Implementation),而非接口(Interface)

真正优秀的企业级 API,像 Google、Stripe 或 GitHub 的 API,它们之所以好用、耐用,是因为它们背后有一套严密的设计哲学规范体系。它们把业务逻辑抽象成了清晰的“资源”和“状态流转”,而不是简单的函数调用。

这就引出了本专栏的核心初衷:我希望带你跳出“CRUD 码农”的思维局限,像架构师一样去思考 API 设计。

这个专栏讲什么?

市面上讲 Go 和 Gin 的教程汗牛充栋,但大多数停留在“术”的层面——教你如何写路由、如何绑定参数。

而本专栏《API 设计之道:从设计模式到 Gin 工程化实现》,试图走一条不同的路。我想带你打通从理论模式工业标准,再到工程落地的完整闭环。

为了达成这个目标,我为你总结了一套“道、法、术”三位一体的学习路径:

1. 道:汲取世界级 API 设计模式的精华

我们不谈空洞的理论,而是将经典的 API 设计模式(Patterns)内化为解决具体问题的思维工具。比如,如何用“字段掩码(Field Mask)”模式解决数据传输过重的问题?如何用“长耗时操作(LRO)”模式解决 AI 推理接口超时的问题?这些模式是无数架构师踩坑后总结出的智慧。

2. 法:对标 Google AIP 业界顶层规范

Google AIP (API Improvement Proposals) 是目前业界公认的、最详尽的 API 设计指南。在专栏中,我们会把每一个设计决策都拿去和 Google AIP 对标。比如,Google 是如何定义“软删除”的?Google 是如何设计分页游标的?我们要学,就学业界最高的标准。

3. 术:基于 Gin 的核心代码落地

光有理论是空中楼阁。我会结合 Go 语言最流行的 Web 框架 Gin,把上述所有高大上的模式和规范,转化为实实在在的 Go 代码。我们会编写通用的中间件、设计泛型的 Controller、封装标准的错误处理包。你不仅能学到“为什么”,还能直接拿走“怎么做”的代码。

专栏模块规划

为了让你学得更顺滑,也为了让每一个知识点都能真正落地,我将专栏分为了循序渐进的四个模块,共 10 讲核心内容:

模块一:基础架构篇

这一模块的目标是帮你“正本清源”。我们将纠正那些随意的接口命名习惯,划清 API 的职责边界,建立起资源导向的架构思维。

  • 01 | 资源导向设计 (ROD):告别 RPC 风格的“动词地狱”
    为什么 Google 的 URL 里从来不出现动词?如何利用 Gin 的路由组重构代码,让 API 像数据库 Schema 一样清晰?
  • 02 | 标准方法论:CRUD 的哲学与 HTTP 动词的精准语义
    PUT 和 PATCH 到底该用哪个?删除是真删还是软删?我们将深入探讨状态变更的原子性,并设计一个符合规范的泛型 Controller。
  • 03 | 非标行为设计:当 REST 无法描述“取消订单”时怎么办?
    并不是所有业务都是增删改查。我们将引入“自定义方法”模式,在保持 REST 风格统一的前提下,优雅地处理翻译、计算等非标动作。

模块二:消息设计篇

这一模块聚焦于“效率与体验”。我们将解决数据传输中的“过度获取”和“性能瓶颈”问题,让你的 API 既灵活又高效。

  • 04 | 字段掩码模式:让前端决定后端返回什么
    移动端只想看头像,后端却返回了整个 User 对象?我们将实现类似 GraphQL 的“按需索取”能力,利用 Go 的反射机制动态裁剪响应体。
  • 05 | 列表分页模式:彻底告别 Offset 分页的性能陷阱
    海量数据下,limit/offset 会导致数据库全表扫描。我们将揭秘大厂强制使用的“游标分页”机制,并在 Gin 中设计安全的 NextPageToken。
  • 06 | 结构化错误处理:RFC 7807 与错误模型的最佳实践
    告别仅仅返回 500 的“盲盒”报错。我们将引入 Problem Details 标准,封装一套让前端和运维都爱不释手的结构化错误处理中间件。

模块三:质量与治理篇

在云原生环境下,高并发是常态。这一模块将通过设计手段,保证 API 的高可用与安全性

  • 07 | 幂等性设计:处理网络抖动与重复请求的“唯一真理”
    用户手抖点了两次“支付”,如何防止重复扣款?我们将结合 Redis 实现请求锁与结果缓存,构建系统级的防重机制。
  • 08 | 流量与配额:构建基于 Redis 的分布式限流器
    如何防止某个租户突发流量打挂整个服务?我们将探讨令牌桶算法在分布式环境下的实现,并标准化输出配额响应头。

模块四:演进与 AI 篇

API 发布了只是开始。这一模块将带你探索 API 的全生命周期管理,以及面向 AI 时代的特殊设计挑战。

  • 09 | 版本演进策略:激进废弃与平滑过渡的艺术
    业务飞速发展,如何修改接口而不让老版本 App 崩溃?我们将对比 URL 与 Header 版本化的优劣,并演示如何优雅地通知客户端接口下线。
  • 10 | 面向 AI 的 API:长耗时任务 (LRO) 与流式响应
    LLM 推理往往需要几分钟,HTTP 连接超时怎么办?我们将实现“异步创建 + 轮询”范式,并利用 Gin 的 SSE 特性实现类似 ChatGPT 的流式响应。

现在订阅,开启进阶之旅

在这个技术快速迭代的时代,框架和工具总是在变,但架构设计模式规范思维是恒久不变的内功。

我希望通过这个专栏,不仅能让你写出一手漂亮、规范、高性能的 Go 代码,更能让你在未来的技术评审中,能够底气十足地告诉团队:“我们之所以这样设计接口,是因为这是符合工业界最佳实践的架构之道。”

《API 设计之道:从设计模式到 Gin 工程化实现》 现已正式上线。

点击这里,或扫描下方二维码

拒绝“面条代码”,从今天开始重塑你的 API 设计思维!

我是 Tony Bai,我在专栏里等你。


还在为“复制粘贴喂AI”而烦恼?我的新专栏 AI原生开发工作流实战 将带你:

  • 告别低效,重塑开发范式
  • 驾驭AI Agent(Claude Code),实现工作流自动化
  • 从“AI使用者”进化为规范驱动开发的“工作流指挥家”

扫描下方二维码,开启你的AI原生开发之旅。


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

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

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

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

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


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

© 2025, bigwhite. 版权所有.

看完《疯狂动物城2》,我发现“完美架构”的谎言被戳破了

2025-12-07 16:06:05

本文永久链接 – https://tonybai.com/2025/12/07/zootopia-2-perfect-architecture-lie-exposed

大家好,我是Tony Bai。

还记得昨天那篇文章里,我还在为那个“标题党”的题目(《如果〈疯狂动物城〉是一个分布式系统…》)向大家“真诚致歉”吗?

当时,带着重温第一部的滤镜,我信誓旦旦地跟大家吹牛,说动物城简直就是 Go 语言构建的云原生架构典范——高效、隔离、完美。

但这周六下午看完《疯狂动物城2》,我不得不承认:草率了,这次“打脸”来得太快。

如果说第一部展示了架构师眼中的“理想国”,那么第二部则残忍地揭开了“完美架构”背后的谎言

看着银幕上那条被大家畏惧、却掌握着关键线索的蛇(Gary),以及那个被冰雪掩埋的真相,我脊背发凉。这哪里是童话?这分明就是一部《大型遗留系统(Legacy System)维护血泪史》

作为架构师,我在这部电影里看到了三个关于“新老技术”的扎心隐喻。

被埋葬的“爬行动物”:那些我们不敢碰的 Legacy Code

在电影里,我们得知了一个惊天秘密:动物城引以为傲的“温控系统”和城市规划,并非现在的创始人(林雪猁, Lynxley)设计的,而是源自一位爬行动物——Agnes(Gary的曾祖母)

但为了打造一个看似光鲜、只有可爱哺乳动物的“新城区”(Tundratown),管理者选择了掩盖历史。他们直接把爬行动物的家园(Reptile Ravine)埋在了厚厚的冰雪之下,假装它们从未存在。

这一幕,像极了我们对待“遗留代码(Legacy Code)”的态度。

在现代化的 Go 微服务、Kubernetes 集群(Tundratown)之下,往往深埋着一套跑了20年的、由 C/C++ 甚至 Fortran 编写的核心交易系统(爬行动物)
* 它们古老丑陋(代码风格甚至没有缩进);
* 它们看起来危险(改一行代码可能崩全站,就像蛇会咬人);
* 所以,我们选择“封印”它。我们用一层又一层的 Wrapper、API 网关把它包裹起来,假装我们已经拥有了一个全新的、完美的系统。

但电影告诉我们:物理掩埋解决不了问题。 当危机来临,那些被忽视的底层逻辑,终将“破土而出”。

Gary 的热感应:老技术独有的“超能力”

电影里有一段非常精彩的情节:朱迪和尼克束手无策时,是蛇 Gary 利用响尾蛇特有的“热感应”能力,看透了迷雾,找到了线索。

这让我想起,每当新技术(如 AI、Web3)甚嚣尘上时,我们往往会轻视那些“老古董”。

  • 我们觉得 Go/Rust 这种现代语言无所不能。
  • 我们觉得 C 语言指针复杂、汇编晦涩、SQL 存储过程老土。

但真到了极端场景——比如需要极致的性能优化、极底层的硬件交互时,我们发现,还得靠那些“老家伙”。Gary 代表的,正是那些虽不时髦、但拥有独特“底层视角”的技术能力。

正如 Go 语言之所以强大,不是因为它切断了过去,而是因为它通过 CGO、通过汇编支持,保留了与底层世界对话的能力。

不要傲慢地认为新技术能替代一切。有时候,解开死锁的钥匙,藏在一行 10 年前写的 C 代码里。

创始人的日记:文档与“去伪存真”

(以下内容涉及核心剧透)

电影的高潮,是朱迪必须找到 Agnes 留下的日记本专利书,才能揭穿谎言,拯救城市。

这本日记,不就是我们梦寐以求的“核心架构文档”吗?

在很多大厂里,随着人员流动(老一辈架构师离职),系统的“设计初衷”往往丢失了。后来的维护者(Lynxley)为了 KPI,可能会歪曲系统原有的设计,堆砌不合理的“补丁”,甚至把系统改造成一个不可维护的怪兽。

朱迪和尼克的冒险,本质上是一次“考古式重构”

  1. 阅读源码(寻找日记);
  2. 理解上下文(Agnes 的初衷是共存,而不是隔离);
  3. 修正架构(打破冰墙,让爬行动物回归)。

这给所有 Go 开发者提了个醒:写代码时,请留下你的“日记”。 好的注释和文档,是连接过去与未来的纽带。不要让后来者通过“猜谜”来维护你的系统。

写在最后

电影结局,爬行动物回到了动物城,与哺乳动物和谐共处。

二宝问我:“爸爸,蛇和兔子真的能做朋友吗?”

我说:“能啊,只要它们互相尊重。”

技术世界也是如此。我们推崇 Go 的简洁、云原生的弹性,但这并不意味着我们要鄙视那些运行在角落里的单体应用老旧语言

真正的“完美架构”,不是推倒重来(Rewrite),而是包容与演进(Evolve)。

它能容得下时髦的微服务(朱迪),也能接纳古老的遗留系统(Gary)。它承认系统的复杂性,并用工程化的手段管理这种复杂,而不是掩耳盗铃。

走出影院,看着手里 2025 年的新技术,再想想公司里那堆跑了 10 年的老代码,我突然多了一份敬畏。

原来,致敬历史,才是通往未来的捷径。


互动话题:

在你的职业生涯中,有没有哪一次“挖坟”经历(维护极老的遗留代码),让你意外地学到了很多东西?或者,你有没有遇到过像 Gary 一样看似可怕、实则核心的“祖传代码”?

欢迎在评论区分享你的“考古”故事!


还在为“复制粘贴喂AI”而烦恼?我的新专栏 AI原生开发工作流实战 将带你:

  • 告别低效,重塑开发范式
  • 驾驭AI Agent(Claude Code),实现工作流自动化
  • 从“AI使用者”进化为规范驱动开发的“工作流指挥家”

扫描下方二维码,开启你的AI原生开发之旅。


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

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

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

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

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


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

© 2025, bigwhite. 版权所有.

“我从未想过学完 Rust 后会转向 Go”—— 这门“无聊”的语言究竟有什么魅力?

2025-12-07 07:55:48

本文永久链接 – https://tonybai.com/2025/12/07/switching-from-rust-to-go-appeal-of-the-language

大家好,我是Tony Bai。

“我从未想过在学习 Rust 之后,我还会转而学习 Go。”

近日,开发者 Abhishek Singh 的一条推文,以其独特的、充满“诗意”的笔触,在开发者社区引发了广泛的共鸣和讨论。这句自白之所以令人惊讶,是因为它描绘了一条在很多人看来“不可思议”的技术迁徙路径:从 Rust——一门以其严谨、强大、表达力丰富著称的现代语言,转向 Go——一门在许多人眼中“简单”、“啰嗦”甚至“无聊”的语言。

这篇充满矛盾感的推文,让我们不得不直面那个核心问题:当剥离了那些华丽的语言特性后,Go 这门看似“无聊”的语言,究竟隐藏着何种独特的魅力,足以让一位经历过 Rust 洗礼的开发者最终与之“和解”,甚至“像写诗一样”乐在其中?

本文,就让我们跟随这位开发者的心路历程,层层深入,一同探寻这个问题的答案。

“无聊”的表象,是可预测性的极致

Singh 在推文中这样描述 Go 的特质:“简单却不简陋,无聊却又令人兴奋”。让我们先来看“无聊”这一面。

对于习惯了 Rust 强大的 enum、模式匹配和 Trait 系统的开发者来说,Go 的世界确实显得有些“朴素”甚至“原始”。日常的编码,充斥着对 struct 的简单定义和一遍又一遍的 if err != nil。Go 缺乏许多现代语言中“炫技”的语法糖,这正是其“无聊感”的来源。

然而,这种“无聊”恰恰是 Go 最重要的魅力之一:极致的可预测性

  • 没有隐式控制流:在 Go 中,代码的执行路径是完全可见的。没有 try-catch 带来的“超级 goto”,没有复杂的继承链和方法重载,也没有操作符重载带来的“魔法”。你看到的,就是即将发生的。
  • 错误处理的确定性:if err != nil 虽然繁琐,但它强制开发者在每一个可能出错的地方,都必须做出明确的处理。这使得错误处理路径成为代码中清晰、可见的一部分,而不是一个随时可能从天而降的“异常”。

让我们看一个简单的文件读取例子。在某些语言中,它可能看起来很简洁:

# Python 示例
try:
    content = read_file("some_file.txt")
    process(content)
except FileNotFoundError:
    handle_not_found()
except PermissionError:
    handle_permission_denied()

而在Go中,则是我们熟悉的“啰嗦”模式:

// Go 示例
content, err := readFile("some_file.txt")
if err != nil {
    if os.IsNotExist(err) {
        handleNotFound()
    } else if os.IsPermission(err) {
        handlePermissionDenied()
    } else {
        // Handle other errors
    }
    return
}
process(content)

Python的 try-catch 看起来更“优雅”,但控制流发生了隐式的跳转。而Go的方式,虽然代码行数更多,但错误的处理逻辑是线性的、局部的、无法被忽略的。对于构建大型、可维护的系统而言,这种看似“无聊”的显式和直白,是一种极其宝贵的资产。它降低了代码的认知负荷,让任何一位团队成员都能快速理解并信任一段代码的行为。这是一种褪去华丽外表后,回归工程本质的、成熟的美。

“简单”的背后,是组合的无限可能

Singh 接着说,Go 是“愚蠢地简单,直到它突然变得复杂”。这份“突然的复杂”,并非源于语言本身的复杂性,而是源于 Go 提供的那些极其简单的原语,在组合之后所爆发出的巨大能量

这其中最具代表性的,就是 Go 的并发模型。

当 Singh 感叹自己“像写诗一样写着 goroutine”时,他所体验到的,正是 Go 并发设计的核心魅力。Go 没有提供复杂的线程库或 async/await 语法,它只给了你两个最基础的构建块:

  • go 关键字:一种极其廉价的、启动并发任务的方式。
  • channel:一种用于在并发任务之间安全通信和同步的管道。

正是这两个看似“简陋”的原语,让开发者能够像拼接乐高积木一样,以一种直观、优雅的方式,构建出极其复杂的并发模式。从“扇入扇出”(Fan-in/Fan-out) 到“流水线”(Pipelines),再到优雅的超时和取消控制。


Go的并发原语,如积木般可被组合成强大的并发模式

这份隐藏在简单之下的兴奋感,正是 Go “简单却不简陋,无聊却又令人兴奋”的最佳注脚。

“中间态”的定位,是务实主义的最终胜利

最后,让我们回到 Singh 那段最富哲学意味的描述:

“从未有过前后之分,而是介于两者之间。”
(Never been before and after but somehow in the middle.)

Go 在现代编程语言光谱中,确实处于一个独特的“中间态”。它是一种务实的、为解决问题而生的工程语言:

  • 它不像 C 那样强迫你手动管理内存,但通过指针让你保留了对内存布局的基本理解。
  • 它不像 Python 那样高度动态,但通过其简洁的语法和强大的工具链,提供了极高的开发效率。
  • 它不像 Rust 那样追求编译期的极致安全,但通过 GC 和明确的错误处理,在安全性和开发速度之间取得了绝佳的平衡。

对于许多从 Rust 这样的语言过来的开发者,初期的体验很可能是一场“战斗”。你会怀念那些强大的抽象工具。然而,当你跨越了这段“排异反应”期,开始真正用 Go 的方式去思考和构建时,你便会与这门语言达成“和解”。

小结

长期用过Go语言进行开发的朋友也许都会发现,Go 并没有试图成为一门在理论上最完美、功能上最丰富的语言。它的所有设计,都服务于一个核心目标:让一个由普通工程师组成的团队,能够以一种可持续的方式,高效地构建出健壮、可维护的大型软件。

在这个热衷于创造复杂性、追逐下一个“银弹”的技术时代,Go的这份“无聊”与“克制”,或许才是一种最稀缺、也最值得我们工程师珍视的品质。

这,或许就是这门“无聊”语言,最深刻、也最持久的魅力。

资料链接:https://x.com/0xlelouch_/status/1990139566150566379


聊聊你的“真香”时刻

Singh 的经历让我们看到了技术选择的另一面。作为 Gopher,你在使用 Go 的过程中,是否有过从“嫌弃它的繁琐”到“享受它的确定性”的心理转变?或者,你认为 Go 的哪一个“无聊”特性,反而在实际工程中救了你的命?

欢迎在评论区分享你的故事和感悟!

如果这篇文章让你对 Go 的设计哲学有了新的理解,别忘了点个【赞】和【在看】,分享给更多在技术选型中迷茫的朋友!


还在为“复制粘贴喂AI”而烦恼?我的新专栏 AI原生开发工作流实战 将带你:

  • 告别低效,重塑开发范式
  • 驾驭AI Agent(Claude Code),实现工作流自动化
  • 从“AI使用者”进化为规范驱动开发的“工作流指挥家”

扫描下方二维码,开启你的AI原生开发之旅。


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

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

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

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

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


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

© 2025, bigwhite. 版权所有.