译文 Rust vs. Go:为什么强强联合会更好

bigwhite-github · 2021年03月17日 · 最后由 windknight 回复于 2021年03月25日 · 532 次阅读
本帖已被设为精华帖!

本文翻译自乔纳森·特纳(Jonathan Turner)和史蒂夫·弗朗西亚(Steve Francia)的文章《Rust vs. Go: Why They’re Better Together》

  • 史蒂夫·弗朗西亚(Steve Francia):在过去的 25 年里,Steve Francia 建立了一些最具创新性和成功的技术和公司,这些技术和公司已经成为云计算的基础,被全世界的企业和开发者所接受。他目前是谷歌 Go 编程语言的产品和战略负责人。他是Hugo、Cobra、Viper、spf13-vim 和许多其他开源项目的创建者,拥有领导世界上最大的五个开源项目的独特荣誉。

  • 乔纳森 - 特纳(Jonathan Turner)在开源领域工作了 20 多年,从小型项目到大型项目,包括帮助微软向开源转型。他是创建 TypeScript 团队的一员,并作为项目经理和设计团队的负责人帮助其成长。他还作为 Rust 社区成员和 Mozilla Rust 团队的一员参与 Rust 的工作,包括共同设计 Rust 的错误信息和 IDE 支持。

虽然其他人可能认为RustGo是竞争性的编程语言,但 Rust 和 Go 团队却都不这么认为。恰恰相反,我们的团队非常尊重其他团队正在做的事情,并认为这两种编程语言是相辅相成的,有着共同的愿景,即在整个行业内实现软件开发状态的现代化。

在本文中,我们将讨论 Rust 和 Go 的优缺点、它们如何相互补充和支持以及我们对每种语言的最佳使用时机的建议。

一些公司正在发掘采用这两种语言的价值以及它们的互补价值。为了从我们的观点转向用户的实际体验,我们采访了三家这样的公司,DropboxFastlyCloudflare,讲述了他们共同使用 Go 和 Rust 的经验。他们的经验之谈将被引用并贯穿本文,为大家提供更进一步的观点。

1. 语言比较

编程语言 Go Rust
创建时间 2009 2010
创建于 谷歌 Mozilla
知名项目 Kubernetes,Docker,Github CLI,Hugo,Caddy,Drone,Ethereum,Syncthing,Terraform Firefox, ripgrep, alacritty, deno, Habitat
典型用途 APIs, Web Apps, CLI apps, DevOps, Networking, Data Processing, cloud apps IoT, processing engines, security-sensitive apps, system components, cloud apps
开发者采用 8.8%(第 12 名) 5.1%(第 19 名)
开发者最爱 62.3%(第 5 名) 86.1%(第 1 名)
开发最想要 17.9%(第 3 名) 14.6%(第 5 名)

2. 相似之处

Go 和 Rust 有很多共同点。两者都是现代软件语言,都是出于为影响软件开发的问题提供一个安全和可扩展的解决方案的需要而诞生的。两者都是为了应对创建者在行业内现有语言中遇到的缺点而创建的,尤其是开发者生产力、可扩展性、安全性和并发性方面的缺点。

当今流行的大多数语言都是 30 多年前设计的。当这些语言被设计出来的时候,与今天有五个关键的区别:

  • 摩尔定律被认为是永恒不变的。
  • 大多数软件项目都是由小团队编写的,并且经常一个人单干。
  • 大多数软件有相对较少的依赖性,大多数是专有的。
  • 安全性是次要的考虑因素......或者根本不是考虑因素。
  • 软件通常是为单一平台编写的。

相比之下,Rust 和 Go 都是为今天的世界而写的,并都采取了相似的方法来设计一种适合今天开发需求的语言。

1) 性能和并发

Go 和 Rust 都是专注于生产高效代码的编译语言。它们还可以方便地使用当今机器的多个处理器,使它们成为编写高效并行代码的理想语言。

  • "使用 Go 使得 MercadoLibre 公司将他们用于这项服务的服务器数量减少到原来的八分之一(从 32 台服务器减少到 4 台),另外,每台服务器可以用更少的功率运行(原来是 4 个 CPU 核,现在减少到 2 个 CPU 核)。有了 Go,该公司省去了 88% 的服务器,并将剩余服务器上的 CPU 削减了一半 -- 产生了巨大的成本节约。"--"MercadoLibre 与 Go 一起成长"

  • "在我们严格管理的环境中,在我们运行 Go 代码的环境中,我们看到 CPU 减少了大约百分之十 [与 C++ 相比],代码更干净,更可维护。" - Bala Natarajan,Paypal

  • "在 AWS,我们也很喜欢 Rust,因为它能帮助 AWS 编写高性能、安全的基础设施级网络和其他系统软件。亚马逊第一个用 Rust 构建的重要产品 Firecracker 于 2018 年公开发布,它提供了开源虚拟化技术,为 AWS Lambda 和其他无服务器产品提供动力。但我们也使用 Rust 来提供亚马逊简单存储服务(Amazon S3)、亚马逊弹性计算云(Amazon EC2)、Amazon CloudFront、Amazon Route 53 等服务。最近,我们推出了基于 Linux 的容器操作系统 Bottlerocket,它是用 Rust 编写的。" - Matt Asay,亚马逊网络服务

  • 我们"看到我们的速度非凡地提高了 1200-1500%! 我们从实现了较少解析规则的 Scala 的模式下的 300-450ms,到实现了更多解析模式的 Rust 模式下的 25-30ms!" - Josh Hannaford,IBM

2) 团队可扩展 ---- 可审查

今天的软件开发是由团队建立的,这些团队不断成长和扩大,经常使用源码控制以分布式的方式进行协作。Go 和 Rust 都是针对团队的工作方式而设计的,通过消除不必要的担忧,如格式 (比如 go 的 gofmt)、安全和复杂的组织,来改善代码审查。这两种语言都需要相对较少的上下文来理解代码的工作,使审查人员能够更快速地使用其他人编写的代码,并审查团队成员的代码和你团队以外的开源开发人员贡献的代码。

  • “我早期的职业生涯有 Java 和 Ruby 的背景,构建 Go 和 Rust 代码对我来说就像卸下了无法承受的重担。当我在 Google 时,遇到用 Go 编写的服务让我很欣慰,因为我知道它易于构建和运行。Rust 的情况也是如此,尽管我只是在更小的工作范围内使用了它。我希望无限可配置的构建系统的日子已经过去了,而语言都有自己的专用构建工具,开箱即用。"-- Sam Rose,CV 合伙人

  • "用 Go 写服务的时候,我往往会松一口气,因为与动态语言相比,Go 的静态类型系统非常简单,易于推理,并发性是一等公民,Go 的标准库既无比精致强大,又切中要害。安装一个标准的 Go,再使用一个 grpc 库和一个数据库连接器,你在服务器端几乎不需要其他的东西,每个工程师都能看懂代码,看懂库。在用 Rust 编写模块时,Dropbox 工程师在 2019 年 Async-await 稳定下来之前,感受到了 Rust 在服务器端的成长之痛,但从那时起,crate(译注:Rust 中的概念) 正在趋向于使用它,我们得到了 Async 模式并从并发中受益。" - Daniel Reiter Horn,Dropbox

3) 开放源码意识

今天一般软件项目所使用的依赖关系数量是惊人的。长达几十年的软件重用目标在现代开发中已经实现,今天的软件可能是复用了 100 多个项目而构建的。为此,开发人员使用软件仓库,这越来越成为软件开发的主旋律,并在越来越广泛的领域应用。开发者所包含的每一个软件包,又有自己的依赖关系。为今天的编程环境而设计出的编程语言需要毫不费力地处理这种复杂性。

Go 和 Rust 都有包管理系统,允许开发人员列出一个简单的清单,列出他们想要构建的包,语言工具就会自动为他们获取和维护这些包,这样开发人员就可以把更多的精力放在自己的代码上,而不是放在对其他包的管理上。

4) 安全性

Go 和 Rust 都很好地解决了当今应用的安全问题,保证了用这些语言构建的代码在运行时不会让用户暴露在各种经典的安全漏洞中,比如缓冲区溢出、use-after-free(内存释放后还使用) 等。通过消除这些顾虑,开发者可以专注于手头的问题,并在默认情况下构建更安全的应用程序。

  • “Rust 编译器在解决您遇到的错误时确实能助您一臂之力。这样一来,您就可以专注于自己的业务目标,而不必寻找错误或解密隐秘消息。” -Josh Hannaford,IBM

  • 简而言之,Rust 的灵活性,安全性和安全性带给我们的益处超过了必须遵循严格的 lifetime,borrow(rust 中的概念) 和其他编译器规则甚至缺乏垃圾收集器所带来的任何不便。这些功能是云软件项目中非常需要的功能,将有助于避免其中常见的许多错误。” —微软高级泰勒·托马斯(Taylor Thomas)

  • "Go 是强静态类型化的,没有隐式转换,但语法开销还是小得惊人。这是通过赋值中简单的类型推理与非类型化的数值常量一起实现的。这使得 Go 比 Java(有隐式转换)具有更强的类型安全性,但代码读起来更像 Python(有非类型变量)。" - Stefan Nilsson,计算机科学教授

  • "当我们在 Dropbox 构建用于存储块数据的 Brotli 压缩库时,我们将自己限制在 Rust 的安全子集上,而且,也限制在核心库(no-stdlib)上,分配器指定为通用。这样使用 Rust 的子集,使得在客户端从 Rust 调用 Rust-Brotli 库,以及在服务器上使用 Python 和 Go 的 C FFI 变得非常容易。这种编译模式也提供了大量的安全保障。经过一些调整,Rust Brotli 的实现尽管是 100% 安全的、经过数组边界检查的代码,但仍然比 C 语言中相应的原生 Brotli 代码快。" - Daniel Reiter Horn,Dropbox

5) 真正的可移植性

在 Go 和 Rust 中,写一个软件,在许多不同的操作系统和架构上运行是很容易的。"一次编写,随处编译"。此外,Go 和 Rust 都原生支持交叉编译,消除了旧编译语言常见的"build farm"的需要。

  • "Go 在生产优化方面拥有很好的特质,比如拥有较小的内存占用,这支持其在大型项目中被用于构建模块,以及开箱即用,易于交叉编译到其他架构。由于 Go 代码被编译成单一的静态二进制,我们可以轻松将其容器化,并且通过扩展,我们可以很轻松地将 Go 部署到任何高可用环境(如 Kubernetes)中。" - Dewet Diener,Curve

  • "当你看一个基于云的基础设施时,通常你会使用类似 Docker 容器这样的东西来部署你的工作负载。通过在 Go 中构建的静态二进制,你可以拥有一个 10、11、12 兆字节的 Docker 文件,而不是带来整个 Node.js 生态系统,或像 Python 或 Java 那样动辄数百兆字节大小的 Docker 镜像文件。所以,交付那个微小的二进制文件是很神奇的。" - Brian Ketelsen,微软

  • "有了 Rust,我们将拥有一个高性能和可移植的平台,我们可以轻松地在 Mac、iOS、Linux、Android 和 Windows 上运行。" - Matt Ronge,Astropad

3. 差异

在设计中,总是要做出一些取舍。虽然 Go 和 Rust 大约在同一时间出现,目标相似,但由于他们决策时选择了不同的取舍,使得这两种语言在关键的方面有所区别。

1) 性能方面

Go 开箱即有出色的性能。在设计上,几乎没有预留任何旋钮或开关可以让你从 Go 中榨取更多的性能。Rust 的设计是为了让您能够从代码中榨取每一滴性能;在这方面,您确实无法找到比 Rust 更快的语言。然而,Rust 的性能提升是以额外的复杂性为代价的。

  • "值得注意的是,在编写 Rust 版本时,我们只在优化方面投入了非常基本的思考。即使只做了基本的优化,Rust 的性能也能超过超手工调整的 Go 版本。这极大地证明了用 Rust 编写高效的程序是多么容易,相比之下,我们不得不对 Go 进行深挖。" - Jesse Howarth,Discord

  • "Dropbox 工程师通过将行对行的 Python 代码移植到 Go 中,往往可以看到 5 倍的性能提升和延迟下降,与 Python 相比,内存使用率往往会大幅下降,因为没有 GIL,进程数可能会减少。然而,当我们的内存受限时,比如在桌面客户端软件或某些服务器进程中,我们会转而使用 Rust,因为 Rust 中的手动内存管理效率大大高于 Go GC。" - Daniel Reiter Horn,Dropbox

2) 适应性/交互性

Go 快速迭代的优势让开发人员可以快速尝试各种想法,并磨合出能解决手头任务的工作代码。通常情况下,这就足够了,可以让开发者腾出手来处理其他任务。另一方面,与 Go 相比,Rust 的编译时间更长,导致迭代时间更慢。这就导致了 Go 在一些场景中能更好地工作,因为更快的周转时间能让开发人员适应不断变化的需求,而 Rust 则在一些场景中茁壮成长,因为在这些场景中,可以给予更多的时间来做出更精致、更高性能的实现。

  • "Go 类型系统的天才之处在于调用者可以定义 Interface,允许库返回仅需满足小接口但却支持扩展的结构。Rust 类型系统的天才设计在于匹配语法与 Result<>的结合,你可以静态地确定每一种可能性都会被处理,永远不必发明空值来满足未使用的返回参数。" - Daniel Reiter Horn,Dropbox

  • "(我) 如果你的用例离客户更近,更容易受到需求变化的影响,那么用 Go 就会好很多,因为持续重构的成本要便宜很多。这就是你能多快地表达新的需求并尝试它们。" - Peter Bourgon,Fastly

3) 可学性

简单来说,真的没有比 Go 更 “平易近人” 的语言了。有很多团队能够在几周内采用 Go 并将 Go 服务/应用投入生产的故事。此外,Go 在语言中是比较独特的,它的语言设计和实践在它 10 多年的生命中是相当一致的。所以,投入到学习 Go 上的时间可以保持很长一段时间的价值。相比之下,Rust 由于其复杂性,被认为是一门难学的语言。一般来说,学习 Rust 需要几个月的时间才能感觉到自如,但这种额外的复杂性也带来了精确的控制和性能的提高。

  • "当时,没有一个团队成员知道 Go,但在一个月内,每个人都在用 Go 写作"--Jaime Garcia,Capital One

  • "Go 与其他编程语言不同的地方在于认知负担。你可以用更少的代码做更多的事情,这使得你更容易推理和理解你最终编写的代码。大多数 Go 代码最终看起来都很相似,所以,即使你在使用一个全新的代码库,你也可以很快上手并运行。" - Glen Balliet 美国运通忠诚度平台工程总监 美国运通使用 Go 进行支付和奖励

  • "然而,与其他编程语言不同,Go 是为了最大限度地提高用户效率而创建的。因此,具有 Java 或 PHP 背景的开发人员和工程师可以在几周内获得使用 Go 的高级技能和培训 -- 根据我们的经验,他们中的许多人最终都喜欢上了 Go。" - Dewet Diener,Curve

4) 精确控制

也许 Rust 最大的优势之一就是开发者对如何管理内存、如何使用机器的可用资源、如何优化代码以及如何制作问题解决方案的控制。与 Go 相比,这并不是没有很大的复杂度成本,因为 Go 的设计并不是为了这种精确的制作,而是为了更快的探索时间和更快的周转时间。

  • >"随着我们对 Rust 经验的增长,它在另外两个轴上显示出了优势:作为一种具有强大内存安全性的语言,它是边缘处理的好选择;作为一种具有巨大热情的语言,它成为了重写组件的流行语言。" - John Graham-Cumming,Cloudflare。

3. 总结/主要收获

Go 的简单性、性能和开发人员的生产力使 Go 成为创建面向用户的应用程序和服务的理想语言。快速的迭代让团队能够快速地作出反应以满足用户不断变化的需求,让团队有办法将精力集中在灵活性上。

Rust 更精细的控制允许更多的精确性,使得 Rust 成为低级操作的理想语言,这些低级操作不太可能发生变化,并且会从比 Go 略微提高的性能中受益,特别是在非常大的规模部署时。

Rust 的优势在最接近 “金属”(指底层机器) 的地方。Go 的优势是在离用户更近的地方最有利。这并不是说两者都不能在对方的空间里工作,但这样做会增加摩擦。当你的需求从灵活性转变为效率时,用 Rust 重写库的理由就更充分了。

虽然 Go 和 Rust 的设计有很大的不同,但它们的设计发挥了兼容的优势,而且 -- 当一起使用时 -- 既可以有很大的灵活性,又可以有很好的性能。

4. 我们的建议

对于大多数公司和用户来说,Go 是正确的默认选择。它的性能很强,Go 很容易采用,而且 Go 的高度模块化特性使它特别适合需求不断变化或发展的情况。

随着你的产品逐渐成熟,需求趋于稳定,可能会有机会从性能的边际增长中获得巨大的胜利。在这些情况下,使用 Rust 来最大限度地提高性能可能很值得你进行初始投资。


Go 技术专栏 “改善 Go 语⾔编程质量的 50 个有效实践” 正在慕课网火热热销中!本专栏主要满足广大 gopher 关于 Go 语言进阶的需求,围绕如何写出地道且高质量 Go 代码给出 50 条有效实践建议,上线后收到一致好评!欢迎大家订阅!目前该技术专栏正在新春促销!关注我的个人公众号 “iamtonybai”,发送 “go 专栏活动” 即可获取专栏专属优惠码,可在订阅专栏时抵扣 20 元哦 (2021.2 月末前有效)。

Gopher Daily(Gopher 每日新闻) 归档仓库 - https://github.com/bigwhite/gopherdaily

我的联系方式:

更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio
astaxie 将本帖设为了精华贴 03月17日 10:27
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册