Go考古:创始人亲述Go语言的“创世纪”
本文永久链接 – https://tonybai.com/2025/07/03/meet-the-go-team-2012
大家好,我是Tony Bai。
2012 年,Google I/O 大会的舞台上,一个刚刚发布 1.0 版本的编程语言团队,正襟危坐。他们面对着全球开发者的审视和提问,这其中,就有三位图灵奖得主级别的传奇人物:Ken Thompson、Rob Pike 和 Robert Griesemer。
那一年,Go 1.0 的发布,是一个历史性的里程碑。它意味着一个承诺“向后兼容、稳定可靠”的 Go 语言,正式诞生。
今天,就让我们扮演一次“Go 语言考古学家”,拂去时间的尘埃,回到那个被称为“创世纪”的时刻,重温 Go Team 核心成员们的亲口讲述,探寻这门语言最纯粹的初心和设计哲学。
我们为何创造 Go?—— “厌倦了等待 C++ 编译”
在访谈中,当被问及创造 Go 的初衷时,Rob Pike 给出了一个近乎“玩笑”却又无比真实的答案:
“我们厌倦了等待 C++ 的编译。”
他生动地描绘了当时在 Google 内部的日常:为了构建一个巨大的 C++ 二进制文件,团队成员不得不在庞大的计算集群上等待超过一个小时。
更令人抓狂的是失控的依赖管理。Rob Pike 提到,他的同事 Mike Burrows(Chubby 的作者)在一次漫长的编译中发现,一个他从未听说过的、与项目毫无关系的头文件,竟然被重复编译了 37,000 次!
“当你用 ifdef 宏来保护依赖时,你最终得到的就是一个极其稠密的、做了太多无用功的依赖之巢。” Rob Pike 总结道。
这个巨大的痛点,催生了 Go 最核心的设计目标之一:从语言层面,彻底解决依赖问题。
- 清晰的依赖图: Go 的导入路径直接明了。
- 拒绝无用功: 编译器会拒绝未被使用的导入。
- 高效的编译链: 设计上保证了“编译包 A 不应再重新编译包 C(如果 A->B->C)”。一旦包 B 被编译,它就携带了关于 C 的所有必要信息。
而对于另一位创始人、C 语言和 Unix 的共同发明者 Ken Thompson 来说,促使他下定决心的“临门一脚”则更为直接和幽默。当被问及为何对 Go 如此热情时,他言简意赅:
“当我试图去读 C++0x(即 C++11)的标准草案时,我就下定决心了。”
全场爆笑。在一门日趋复杂的巨型语言面前,三位大师不约而同地选择了回归简单。
Go 的“魔法”时刻 —— 那些改变编程方式的设计
Go 的简洁并非简陋。在这次访谈中,创始人们也分享了那些让他们自己都感到惊喜和自豪的“魔法”设计。
Slices (切片):Ken Thompson 的神来之笔
Rob Pike 回忆道,团队曾为了“数组”到底该如何工作而苦恼了整整一年。他们既想要静态检查的固定长度数组,又渴望某种形式的可变长度数组。在无数次的挣扎后,有一天,Ken Thompson 带着 slice 的想法走进办公室。
“起初我们并不确定这是不是正确答案,” Rob Pike 说,“但一旦我们开始使用它,一切都变得显而易见。” 一个简单而优雅的设计,完美地解决了这个旷日持久的难题。
Interfaces (接口):Rob Pike 的挚爱
对于 Rob Pike 而言,接口是他认为 Go 中最强大的特性。
“接口深刻地改变了我对软件开发的思考方式。一个程序由这些可以轻松‘粘合’在一起的东西组成,这种感觉太棒了。它改变了软件被构建的方式。”
Go 的接口是隐式实现的。这种非侵入式的设计,让组件之间的耦合度降至最低,极大地促进了代码的解耦和可组合性。
Packages (包):看似显然,实则艰难
今天我们觉得理所当然的 Go 包机制——一个包可以由多个文件组成,包内全局变量可以任意顺序声明——在当时也是经过了无数次辩论才最终成型的。
“它看起来似乎是显而易见的,但要弄清楚这一点真的非常困难。” Rob Pike 感叹道。这种“松散”的包设计,极大地简化了代码组织和重构的难度。
有所为,有所不为 —— Go 的设计权衡
当被问及如何看待 D 语言等其他试图改进 C++ 的语言时,Robert Griesemer 阐述了 Go 截然不同的设计哲学:
“我的印象是,D 语言会像 C++ 一样不断成长。而在 Go 中,我们试图采取完全相反的方式:尽可能地移除东西,将其简化到骨架,只保留你构建一切所需的绝对最小值。”
他相信,如果这些小组件是正交且能良好协作的,最终得到的东西会比拥有大量相互掣肘的特性的语言更强大。
这种“少即是多”的哲学,体现在 Go 对许多“流行特性”的刻意“缺失”上。当被问及“最庆幸 Go 缺失了什么特性”时,团队成员提到了:
- 类型继承体系 (Type Hierarchy)
- 可选参数 (Optional Arguments)
- 列表推导式 (List Comprehensions)
- 三元运算符
Rob Pike 指出,在 Java 或 C++ 中,你通常从设计类型继承树开始。这项工作耗时耗力,一旦发现设计有误,回头修改的成本极高。Go 通过移除类型继承,让程序在演进过程中更易于调整和适应。
为了凸显 Go 的简洁与 C++ 的复杂之间的对比,Rob Pike 更是转述了当时未能到场的 Russ Cox 的一句玩笑话,它为 Go 的哲学做了最好的注脚:
“C++ 的风格指南里条条框框,而 Go 的风格指南第一句或许应该是:你可以使用这门语言的全部。”
回望 2012 的“预言” —— 那些已实现和仍在路上的事
考古的乐趣,在于用今天的视角去审视昨天的预言。在 2012 年,Go Team 对未来的展望,如今看来既有惊人的远见,也留下了些许历史的印记。
- 对 Go 1.1 的精准预言: 他们当时预测 1.1 版本将专注于性能提升、GC 改进、调度器优化和对更多操作系统的支持。这与后来 Go 1.x 系列的演进路径完全吻合。
- 对 Go 2.0 的务实态度: 团队明确表示“Go 2 遥遥无期”,Go 2 的新想法将来自于使用 Go 1 中发现的真实需求。这个务实的态度至今仍在指导着 Go 的发展。
- 最大的“失误”? 当被问及此,团队坦诚地提到了 nil 指针(Tony Hoare 的“十亿美元的错误”),以及循环变量的作用域问题。这些话题,至今仍在社区中被热烈讨论。
- 未解的难题与渴望: Rob Pike 当时多次提到,他们非常想实现但还没找到完美方案的“网络化的 Channel (netchan)”,以及对一个真正的“抢占式调度器”的渴望。这些难题,在后来的岁月里,通过不同的方式被逐步探索和解决。
小结:回到源头,理解初心
穿越时空,回到 Go 语言的“创世纪”现场,我们听到的不是高深莫测的理论,而是一群务实的工程师,为了解决自己在日常工作中遇到的真实、具体的痛点,而进行的一场充满智慧、权衡与热情的创造。
他们对简洁的极致追求,对工程效率的深刻理解,以及对“少即是多”的坚定信念,共同塑造了今天我们所热爱的 Go 语言。
理解这段历史,就是理解 Go 的灵魂。
参考资料链接:https://www.youtube.com/watch?v=sln-gJaURzk
你的Go技能,是否也卡在了“熟练”到“精通”的瓶颈期?
- 想写出更地道、更健壮的Go代码,却总在细节上踩坑?
- 渴望提升软件设计能力,驾驭复杂Go项目却缺乏章法?
- 想打造生产级的Go服务,却在工程化实践中屡屡受挫?
继《Go语言第一课》后,我的《Go语言进阶课》终于在极客时间与大家见面了!
我的全新极客时间专栏 《Tony Bai·Go语言进阶课》就是为这样的你量身打造!30+讲硬核内容,带你夯实语法认知,提升设计思维,锻造工程实践能力,更有实战项目串讲。
目标只有一个:助你完成从“Go熟练工”到“Go专家”的蜕变! 现在就加入,让你的Go技能再上一个新台阶!
商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。
评论