新项目用 Rust 还是 Go ?

新项目用 Rust 还是 Go ?

如果你用 Rust 语言或 Go 语言编写过代码,就会发现它们之间有些相似之处和不同之处。这两种语言的设计目标有重叠的部分,但也有很多差异。正如我们知道的,该如何选择语言取决于要解决的问题。

很幸运,我们找到了一位对这两种语言都有着丰富经验的工程师 — Damien Stanton,并与他进行了一次交流。他从 2014 年开始接触到 Rust 和 Go 语言,当时他从事的某个项目需要能够编译静态二进制文件。由于 Go 和 Rust 语言均具备这样的能力,因此他深入研究了每种方法的优缺点。

虽然在那个项目上他的大部分专业工作都是以 Go 语言实现的,但是他对于 Rust 社区解决各种问题抱有很大的兴趣,比如错误处理,泛型和并发。

于是他花了大量时间研究这两种语言,而且最终他将研究成果提交给了 Go 语言社区——“Go 程序员看 Rust”。

下面就是我们与 Damien 的交流内容,包括:两种语言的的差异、相似之处、以及二者之间的一些争议点。

你觉得它们(Rust 和 Go)有哪些相似之处?设计目标的重叠指什么?

这两种语言以及背后的生态都在尝试解决许多相同或类似的问题。

它们都是介于偏底层的系统语言(就像 C 或 C++ 语言)和基于运行时的语言(比如 Java 或 Python)之间。但它们都更适用于系统编程领域。

易于部署/分发和方便交叉编译是我认为它们都做得很好的点,同时内存安全对两种语言也很重要。它们都天然具备解决高性能或高并发的问题的能力,而这也是使用传统的 Python 或 Java 不容易做到的。

对于内存管理方面,二者使用了完全不同的方式。同时稳固、可靠、易于维护和升级二者做得都很好。

2020年,很多社区或组织似乎都表达一种观点:同时使用这两种语言来解决不同的问题。那么你目前一般会如何选择?

  • 使用 Go:曾经有观点说“Go 语言是更友好的 C 语言”。但是就我的使用经验和观察来说,Go 可能是 Java 的更好继承者,因为它适合构建大型分布式系统。这也是你看到的像 Kubernetes 和 Docker 使用 Go 编写的原因。
  • 使用 Rust:更适用于对时间/空间要求苛刻的场景,比如微控制器。另一个重要场景就是 Web Assembly。在 Rust 社区中,构建编译成 Web Assembly 并跑在浏览器中工具非常多。于这一点我认为 Rust 更类似于C++。

如果需要在这两种语言之间做选择,那我认为更多是从编程经验和能力上考量,而非要解决的特定问题。

根据我在初创公司的经验,当时我们选择使用 Go,更多是因为它更容易上手,适合当时处于快速增长时期的团队。新的团队成员可以迅速开始产出。

但对于 Rust 而言就不是如此了。由于它独特的内存模型等特点,Rust 的学习曲线更陡峭,更难上手。当然我也发现那些具备 C++ 或 Java 背景的团队可能会选择它。

围绕 Rust 和 Go 的讨论很多,哪些点是更吸引你的?

泛型

在 Go 社区内部,最常见的抱怨就是范型的缺失。相比而言,Rust 具有强大的类型系统并支持泛型。它的设计哲学不同于 Go ,类型系统方面借鉴了 Haskell 和 C++。

GopherCon 2019 上,有一个关于范型的演讲提出了一种语法表达。我认为在 Go v2.0之前,肯定会看到对于范型的正式支持。(如果不得不猜测的话,大概在v1.16~v1.19之间)。

并发

在过去的六个月里,Rust 并发特性发生了很大变化。

Rust 和 Go 使用者之间的常见讨论就是并发。Go 具有 goroutine+channel 的并发模型,而 Rust 则具备更简单的多线程模型。类似于 C++ 或 Java,但是具有更好的线程间通信能力,比如 MPSC channel(非常类似于 Go channel)。

但是现在,Rust 朝 Future 模型发展,其实就是我们已经熟悉的 async/await 模型,以同步的方式和思维编写代码,但以异步方式执行。

Rust 还有一个功能非常强大的宏(macro)系统,可以使编译器做很多工作,比如生成代码,除此之外还有更多可以细粒度控制的细节。所以这意味着 Rust 的学习挑战很大。

Go 的构建工具

长期以来,构建工具一直是 Go 程序员的抱怨。直到最近我们才切换到了 Go mod,整体来说,Go 的相关工具够用但还不够强大。比如开发人员希望为他们的编辑器提供稳定的语言服务器(languange server,可参考 lsp 协议),易于使用的依赖管理解决方案以及良好的自动文档和发布工具等等。另一方面,Rust 的 cargo 相当出色,完善的文档,并且可以轻松扩展子命令。

Fuschia:Google 的 Android 后继产品

关于 Go 与 Rust 的一个有趣的用例是 Google 的新软件 Fuschia,该软件最终将取代Android。

Google 主要使用 C++ 构建该系统,但是其中有一些来自 ChromeOS 的 Rust 组件,其中大量使用 Rust。为了确定用户如何为 Fuschia 编写程序(即,用户级程序而不是内核组件),他们研究了五种语言,包括 Go 和 Rust。在这种情况下,Go 的内存管理开销会导致过多的延迟。这是内存管理语言的普遍问题,最终只能用 C++ 或 Rust 编写面向用户的代码。

发布周期

这两种语言有非常不同的发布方式和发布周期:

  • Go 的发布周期:有些规律但依然是一个黑匣子;核心团队之外没有人真正知道何时发布新版本,而且通常是通过一篇博客就宣布发布了。在 Gerrit/GitHub 上以 issue 形式存在的文档很多,不够完善和透明。
  • Rust 的发布周期:更加透明;核心团队在 YouTube 上记录了所有团队会议,你可以实实在在看到他们的讨论。特别是看到语言背后的设计思考和决策很有趣。Rust 具有明确的滚动发布周期,具有良好的稳定/测试版/尝鲜版说明。

我个人认为,从长远来看,使所有内容完全开放和透明可能更好。

总而言之,很有趣的是看到它们的组织风格如此不同,但是两种语言都取得了巨大的成功。Go 和 Rust 都是很棒的语言,我希望两个社区的新手和资深程序员可以聚在一起,互相学习!

原文地址:dmv.myhatchpad.com/insi

编辑于 2020-04-21 13:33