Microsoft TypeScript 开发人员解释为什么他们选择 Go 而不是 Rust、C#
微软的 Anders Hejlsberg 解释说,选择 Go 作为其 TypeScript 编译器端口是因为它的原生代码、垃圾收集以及对内存和数据布局的出色控制。
上周,微软宣布 TypeScript 编译器将移植到一种新的编程语言——Go。随后,网上掀起了一轮热议……每个人都对这个高风险的决定感到着迷,一些评论者甚至忍不住对开发团队选择新编程语言的做法提出了质疑。
为什么选择 Go?为什么不选择微软自己的 C# 或者时下热门的Rust?
TypeScript的开发者们很快就发现自己身处GitHub、Reddit、YouTube和Hacker News 等平台的临时研讨会之中,他们纷纷解释自己的决策过程,以及 Go 诸多显而易见的优势。在反复的讨论中,他们共同探讨了几种不同编程语言各自的优点,并进行了一次出人意料的、颇具教育意义的探索。
在此过程中,他们甚至详细解释了为什么决定将 TypeScript 的编译器移植到 Go……
但为什么不使用 C#?
TypeScript 当前的编译器是用 TypeScript 语言编写的。但在 Reddit 上,一位评论者提出了一个有趣却又无可辩驳的反驳: C#“几乎具备”重写 TypeScript 代码所需的一切。
“好吧,你可以把这个告诉创建 Typescript 和 C# 的人,但他不同意你的观点。”
确实,这是Anders Hejlsberg在宣布这一举措的视频中提出的一个问题。“你们中的一些人可能会问,‘为什么不是我最喜欢的语言?为什么不是 C#?为什么不是 Rust?为什么不是 C++?’”
Hejlsberg 回答说,Go 是“我们能接触到的最底层语言,它能在所有平台上提供完整、优化的原生代码支持,对数据布局有很强的控制力,能够使用循环数据结构等等。它还提供了垃圾收集器和自动内存管理功能,以及强大的并发访问能力。”
Hejlsberg 还在 密歇根州安娜堡每月一次的 TypeScript 聚会 YouTube 频道的Zoom 特别采访中回答了这个问题。Hejlsberg 将 C# 描述为“字节码优先”。此外,就性能而言,C# 的提前编译功能并非在所有平台上都可用,而且“它没有经过十年或更长时间的强化……”
“然后我认为 Go 在数据结构布局和内联结构等方面具有更强的表现力。”
但微软最初的 TypeScript 编译器代码库也有一些独特之处。Hejlsberg 在 Zoom 采访中表示,C# 是一种面向对象的语言,而 TypeScript 使用的“类”却“非常少”。“事实上,核心编译器根本不使用类……”
Go 注重函数和数据结构,而 C# 则高度依赖面向对象编程 (OOP)。我们必须先切换到 OOP 范式才能迁移到 C#……相比迁移到 Go,这种迁移的阻力更大。
Reddit 上的一位评论者甚至将微软的所有官方答案收集到一张方便的图表中——Go 有一个经过充分测试的原生优先选项,支持他们所需的所有平台(与 C# 不同)。
为什么不使用 Rust?
TypeScript 开发负责人Ryan Cavanaugh在 Reddit上发表了一条获得 1,305 个赞的评论,承认了人们的好奇心。“我们选择 Go 的时候就知道,肯定会有人质疑我们为什么不选择 Rust(或其他语言)。”
“这是一个很好的问题,因为 Rust 是一种优秀的语言,并且除非有其他限制,否则它是编写新的本机代码时的首选。”
Cavanaugh 写道,Rust 和 Go 都擅长表示数据,拥有“出色的”代码生成工具,并且在单核系统上表现良好。“我们认为,Rust 在其设计目标上取得了巨大成功,但‘从这个特定的 JavaScript 代码库直接移植到 Rust’,这很合理地不是它的设计目标之一。”
“它也不是 Go 的语言之一,但就我们目前编写的代码而言,它确实表现得相当不错。”
Cavanaugh 分享了一些内部消息:他们确实尝试过 Rust。但他们希望新的代码库“在算法上与现有代码库相似”,而 Rust 并不合适。“我们尝试了无数种方法,希望能找到一种能让移植方法在 Rust 中易于处理的表现形式,但所有这些方法要么存在不可接受的权衡(性能、人体工程学等),要么沦为‘自己写垃圾回收’式的策略。有些方法已经很接近了,但通常需要投入大量不安全的代码……”
Cavanaugh在 GitHub 上的项目常见问题解答中解释说,他们也尝试过其他语言,甚至“对现有原生 TypeScript 解析器(如swc、oxc和esbuild)所使用的方法进行了深入研究”。Cavanaugh 说,他们得出了两个重要结论。
“许多语言都适合从头开始重写的情况。”
“考虑到针对这种情况的多个标准,Go 的表现是最好的……”
Reddit 上有人指出 Go 提供了“更细粒度的内存控制”——Ryan Cavanaugh 也表示赞同,Go 在内存分配方面“拥有出色的控制力”。使用池分配器绕过 Go 的内置分配器“非常简单(并且易于实验,无需更改下游使用情况)。”
相比之下,Cavanaugh 补充道,“Rust 对‘何时释放内存’有更好的控制,但在类型检查器中,在完成整个批处理之前几乎没有什么可以释放的,所以在这种情况下,你实际上并没有比 GC 模型获得任何东西。”
在常见问题解答中,卡瓦诺还对 Go 对内存布局的控制表示赞赏—— 并且它做到了这一切“而不需要整个代码库不断关注内存管理”。
因此,当谈到 Rust 时,Cavanaugh 在 Reddit 上解释说,他们面临两个选择:
“用 Rust 彻底从头重写,这可能需要数年时间,并且会产生一个不兼容的 TypeScript 版本,实际上没有人会使用它……”
“只需在 Go 中进行移植,大约一年后就能获得一些可用的东西,并且在语义方面具有极高的兼容性,在性能方面也极具竞争力。”
在Hacker News 的一篇评论中,Cavanaugh 提醒读者,SWC(Speedy Web Compiler)项目在 2022 年也选择将TypeScript 类型检查器tsc移植到 Go 语言中。(项目创始人 DongYoon Kang 指出,tsc “使用了大量共享可变性,并且很多部分依赖于垃圾回收。尽管我是 Rust 的拥护者和信徒,但感觉它并不是完成这项工作的合适工具。”)
卡瓦诺在Reddit 上的一条评论中表示:“kdy1 的初始 Go 移植版本无疑找到了正确的总体方法。”
优点和缺点
在 Zoom 采访中,安德斯承认 TypeScript 的类型系统比 Go 的“丰富得多”。但另一方面,Go“实际上对位操作和将标志打包成int提供了出色的支持。事实上,它对各种数据类型的支持比 JavaScript 好得多……你可以使用字节、短整型、整型和 64 位整型,以及有符号和无符号的……在 JavaScript 中,一切都是浮点数。就是这样。”他笑着说。“我的意思是,你想表示真还是假?是的,那就用八个字节吧……”
Hejlsberg 说,Go 的意义远不止于此。“我们还可以将它们布局为结构体——你知道,内联的,数组的形式。而且效果显著!我们的内存消耗大约是旧编译器的一半……如果你能精简数据结构,速度就会更快。”
说到这里,Hejlsberg 停下来思考这是多么漫长而奇怪的旅程,他说,如果有人告诉他“Anders,你将用 JavaScript 编写十年的编译器”,他会笑着说……
“你疯了。”
“JavaScript 从来就不是真正意义上的计算密集型、系统级工作负载的语言……”他说,“而 Go恰恰是这样的……Go 是一个系统级工具,而我们是一个系统级程序。”
Hejlsberg 还参与了GitHub 上“为什么选择 Go”的讨论,他强调使用 Go 的决定“强调了我们对务实工程选择的承诺”。
“在微软,我们利用多种编程语言,包括 C#、Go、Java、Rust、C++、TypeScript 等,每种语言都是根据技术适用性和团队生产力精心选择的。”
庆祝力量
作为 C# 的原始设计者,Hejlsberg 一定很自豪地指出:“到目前为止,C# 仍然是内部最受欢迎的语言。” 他甚至强调,微软仍然在投资 C# 和 .NET,“因为它们拥有无与伦比的生产力、强大的生态系统和强大的可扩展性。”
他说他们甚至尝试过用 C# 原型来制作 TypeScript 的编译器,但“Go 成为了最佳选择,它为树形遍历提供了出色的人体工程学设计,易于内存分配,并且代码结构与现有编译器非常相似,从而更容易维护和兼容。”
Hejlsberg 补充道,从零开始将是一个完全不同的问题,但“这不是一片绿地 —— 它是一个现有代码库的移植,耗费了 100 个人年的投入……”由于代码库“全是函数和数据结构”——没有类——Go 只是“在映射上更加一对一……惯用的 Go 看起来就像我们现有的代码库,因此移植工作大大简化了。”
Hejlsberg 利用这个机会表示“在微软,我们庆祝编程语言多样性带来的力量。”
他的评论最后也从历史角度进行了总结。“说实话,微软用 Go 语言编写 TypeScript 编译器在过去几年里是不可能实现的,也是不可想象的。” 但“在过去的几十年里,我们看到了微软对开源软件坚定而持续的承诺,将开发者生产力和社区协作放在首位。” Hejlsberg 认为,如今微软致力于“为开发者提供最好的工具,让他们不受内部政治或狭隘限制的束缚。”
这种为每项具体工作选择合适工具的自由最终将惠及整个开发者社区,推动创新、提高效率并改善成果。而且,10 倍的成果是无可争议的!
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。