Rust 和 Go 是两种现代语言,近年来获得了巨大的关注,每种语言都有自己独特的优势和权衡。在这篇文章中,我们将深入探讨 Rust 和 Go 之间的差异,重点关注性能、语言功能和其他关键因素,以帮助您针对您的开发需求做出明智的决定。
2023 年,我们有一千个学习 Rust 的理由。
8 月 7 日,Rust 基金会发布了2022 年 Rust 调查报告结果。报告显示,Rust 的采用率持续增加。超过 90% 的受访者表示他们是 Rust 用户;Rust 用于大部分编码工作,比前一年大幅增长 51.8%。
毫无疑问,Rust凭借其出色的内存安全性和并发性能,越来越成为开发者关注的焦点。不过,也很难忽视Go这个曾经被选为年度编程语言的相对"老牌"选手。
Go语言诞生于2009年,因其独特的并发模型和强大的性能优势,从一开始就受到了极大的关注。值得注意的是,和Rust语言一样,Go语言的创造者也"讨厌"C++,而Go也是云原生的主导语言。
在 Stack Overflow 2022 开发者调查中,在"一种让人又爱又恨的编程语言"这个问题的 7 万份回复中,程序员显然更喜欢 Rust,其中 86% 的人表示喜欢 Rust,64% 的人表示喜欢 Go。面对Rust的火爆状态,一些开发者扪心自问:2023年Go还值得学习吗?
另外,这两天,到底选择 Rust 还是 Go 也成为 Hacker News 上的热门话题:
不得不说,Go 和 Rust 绝对都是优秀的编程语言。它们现代、强大、多功能,并提供出色的性能。但直接比较 Go 和 Rust 确实没有意义,哪个更好,因为每种编程语言背后都代表着一系列深层的权衡。不同的语言会针对不同的需求进行优化,所以我们在选择语言的时候,也应该考虑我们想要用它来解决什么样的问题。所以我们将从Go和Rust语言的适用场景出发,讨论Go和Rust的设计之"道"。
虽然 Rust 和 Go 在语法和风格上有很大差异,但两者都是构建软件的一流工具。下面我们开始具体分析。
Go 与 Rust:相似之处
Rust 和 Go 有很多共同点,这就是人们经常比较两者的原因。他们有什么共同目标?
Rust 是一种低级静态类型多范式编程语言,更注重安全性和性能。
和:
Go 是一种开源编程语言,可以轻松构建简单、可靠且高效的软件。
内存安全
Go 和 Rust 都是非常重视内存安全的现代编程语言。在 C 和 C++ 等古老语言的几十年里,我们已经清楚地认识到,错误和 bug 的核心原因之一是对内存的不安全/不正确访问。
所以Rust和Go各自给出了不同的解决方案,但两者的目标都是在内存管理方面更加智能、安全,帮助开发者编写出性能优异的正确程序。
快速、紧凑的可执行文件
两者都是编译语言,这意味着程序可以直接翻译成可执行的机器代码,从而可以将程序部署为单个二进制文件。与 Python 和 Ruby 等解释性语言不同,我们不需要随程序附带解释器和大量库/依赖项。作为这一核心优势的直接体现,Rust 和 Go 程序往往比解释性语言运行得更快。
通用语言
Rust 和 Go 都是功能强大且可扩展的通用编程语言,可用于开发各种现代软件 - 从 Web 应用程序到分布式微服务,再到嵌入式微控制器和移动应用程序等等。
两者都拥有优秀的标准库和蓬勃发展的第三方生态系统,再加上强大的商业支持和庞大的用户群。两者都已存在多年,并将在未来几年继续蓬勃发展。如今,学习 Go 或 Rust 将是一项非常合理的时间和精力投资。
务实的编程风格
它们既不是过度函数式语言(例如 Scala 或 Elixir),也不是完全面向对象的语言(例如 Java 和 C#)。相反,Go和Rust虽然都具有函数式和面向对象的编程功能,但它们始终强调一种务实的导向------即以最合适的方式解决问题,而不是通过"意识形态"强迫大家按照特定的方式做事。 "。
但如果你真的喜欢函数式编程风格,Rust 方面还有更多相关的工具选项,这也是 Rust 相对于 Go 的优势之一。
我们当然可以争论什么是真正的"面向对象"语言。但公平地说,C++、Java 或 C# 用户所期望的面向对象编程风格在 Go 或 Rust 中并不真正存在。
大规模开发
Rust 和 Go 都为大规模编程提供了许多有用的功能,因此它们都可以适应大型开发团队和大型代码库的实际需求。
例如,C 程序员多年来一直在争论如何放置括号,以及代码是否应该使用制表符或空格缩进;但Rust和Go已经使用标准格式化工具(Go有gofmt,Rust有rustfmt)完全解决了这些问题。它们会自动使用一致的样式重写您的代码。
并不是说这种特殊的格式很微妙,而是 Rust 和 Go 程序员更加务实,更喜欢统一的实现标准。
gofmt的风格无人喜欢,但gofmt却是所有人的最爱。
这两种语言的另一大优势体现在构建管道上。两者都具有优秀的、内置的、高性能的标准构建和依赖管理工具。这意味着程序员不必与复杂的第三方构建系统抗衡,也不需要每隔几年就学习一个新系统。
Rust 还是 Go?
说了这么多问题,而且两种语言都设计得这么好,功能也这么强大,那么这次比赛有什么结果吗?或者,既然两者都是很好的选择,为什么人们仍然在社交媒体上感到愤怒,写长篇评论博客文章说"Rust 是白痴的"或"Go 根本不是一种编程语言"之类的刺耳的话?
当然,有些人只是想发泄情绪,但这显然无助于解决实际问题。至少当涉及到在项目中使用哪种语言,或者使用哪种语言闯入编程世界时,大声的声音显然无助于做出正确的选择。
让我们回到大人的讨论中,看看Rust和Go在理性分析下有何优缺点。
Go 与 Rust:性能
如前所述,Go 和 Rust 生成的程序都很快,因为它们无需经过解释器或虚拟机即可编译为本机机器代码。
但Rust的性能仍然更好,甚至可以与被誉为业界性能基准的C和C++相媲美。而且与这些老式语言不同的是,Rust 还提供了内存安全和并发安全机制,同时几乎不影响执行速度。Rust 还允许开发人员构建复杂的抽象,而不会在运行时造成性能损失。
相比之下,虽然 Go 程序性能良好,但它们的设计重点是开发速度(包括编译)而不是执行。Go程序员更喜欢清晰易读的代码,因此运行速度会慢一些。
Go 编译器也不会花费太多时间生成最高效的机器代码,它更关心快速编译大量代码。因此,在运行时基准测试中,Rust 程序常常击败 Go 程序。
Rust 的运行时性能也非常一致且可预测,因为它不使用垃圾收集。Go 的垃圾收集器非常高效,并且经过优化以尽可能缩短暂停时间(Go 的每个新版本的暂停时间都会变短)。但无论如何,垃圾收集总是会在程序的行为方式中引入一些不可预测性,这对于某些应用程序(例如嵌入式系统)来说可能是严重的甚至是完全不可接受的。
简单
如果一种编程语言太难学习并且将大多数人拒之门外,那么它的功能有多么强大也无济于事。Go 似乎是故意设计的,以将其与 C++ 等日益复杂的语言区分开来:它的语法非常少,关键字非常少,甚至函数也很少。
这意味着Go语言很容易学习,稍微了解一下就可以用它来编写各种程序。
这里的关键是"简单"二字。当然,简单并不意味着容易。但小而简单的语言肯定比大而复杂的语言更容易学习。实现一种效果的方法并不多,因此高质量的 Go 代码几乎总是看起来相同。这样做还有另一个好处:我们可以快速了解我们不熟悉的服务在做什么。
Go的核心本体很小,但是标准库却很强大。也就是说,除了 Go 语法之外,我们的学习曲线还必须考虑标准库的这一部分。
另一方面,将功能从语言转移到标准库意味着大家只需要专注于学习与当前开发需求相关的库即可。
Go在设计上还充分考虑了大规模软件开发的需求,能够强有力地支持大型代码库和开发团队。在这种场景下,新开发人员必须能够快速上手。为此,Go 社区始终优先考虑程序的简单性、清晰性、多功能性和直接性。
Go 是我使用过的最高效的语言之一。口头禅是:今天就解决实际问题。
功能
Rust 比其他几种编程语言支持更多的复杂性,因此相应的实现范围也更大。
Rust 经过专门设计,包含各种强大且有用的功能,帮助程序员用更少的代码做更多的事情。例如,Rust 的 match 函数使得快速编写灵活且富有表现力的逻辑成为可能:
但也因为Rust的设计考虑较多,所以学习起来比较困难,尤其是在初级阶段。不过没关系,C++ 或 Java 毕竟有很多东西要学,而且它甚至不提供 Rust 的内存安全等高级功能。
所以批评 Rust 过于复杂的声音确实没有道理:它的设计就是为了强调表现力和丰富的功能,我们不能期望它在享受好处的同时又如此简单纯粹。
所以 Rust 当然有它自己的学习曲线。但只要克服了这个困难,前面的路就会平坦。
Rust 与 C++ 和 D 争夺程序员的心智份额,这些程序员准备接受更复杂的语法和语义(可能还有更高的可读性成本),以换取最大可能的性能。
虽然 Rust 和 Go 互相借用了一些功能(例如泛型),但可以公平地说 Rust 的功能比 Go 的更好。
并发性
大多数语言都提供某种形式的并发编程支持(即同时执行多个操作),但 Go 是为此而设计的。Go 不使用操作系统线程,而是提供了一种轻量级替代方案:goroutines。
每个 goroutine 都是一个独立执行的 Go 函数,Go 调度程序将其映射到受控制的操作系统线程之一。也就是说,调度程序可以非常有效地管理大量并发 goroutine,同时仅使用有限数量的操作系统线程。
因此,我们可以在单个程序中运行数百万个并发 goroutine,而不必担心严重的性能问题。正因为如此,Go 是针对 Web 服务器和微服务等大规模并发应用场景的完整解决方案。
Go 还为 goroutine 提供通道,这是一种快速、安全、高效的通信和共享数据的方式。Go的并发设计水平确实很高,使用体验相当轻松愉快。
总的来说,并发程序的设计是非常困难的,用任何语言构建可靠、正确的并发程序绝非易事。不过,由于在项目之初就考虑到了这个需求,Go 中的并发编程机制已经做得尽可能简单,并且集成得很好。
Go 使得构建一个精心分解的应用程序变得非常容易,该应用程序在部署为一组微服务时充分利用并发性。
Rust 也可以做这些事情,但可以说它更难一些。在某些方面,Rust 对防止与内存相关的安全漏洞的痴迷意味着程序员必须不遗余力地执行在其他语言(包括 Go)中更简单的任务
相比之下,Rust中的并发机制才刚刚落地,尚未稳定下来,所以欢迎大家继续关注这个活跃的发展方向。这也是有好处的。例如,Rust的rayon库提供了一种非常优雅且轻量级的方法,可以将顺序计算转换为并行计算。
虽然在 Rust 中实现并发程序可能并不容易,但它仍然是完全可行的,并且这些程序也受益于 Rust 精心设计的内存安全保证。
以标准库的 Mutex 类为例:在 Go 中,我们可能会在访问某些东西之前忘记获取互斥锁;但在 Rust 方面,我们完全不必担心。
Go 将并发作为首要概念。这并不是说您无法在 Rust 中找到 Go 面向参与者的并发性的各个方面,而是将其留给程序员作为练习。
安全
如前所述,Go 和 Rust 都有自己的方法来防止各种常见的编程错误,尤其是与内存管理相关的问题。但Rust更进了一步,可以说是不遗余力地保证大家不犯意想不到的安全错误。
也就是说,Rust 的编程体验与几乎任何其他语言都不同,并且在首次引入时可能非常具有挑战性。但在很多开发者看来,这种努力显然是值得的。
包括 Go 在内的许多语言也提供了帮助程序员避免错误的工具,但 Rust 将这种效果提升到了一个新的水平。许多不正确的程序甚至根本无法编译。
Rust 与 Go:差异
虽然 Rust 和 Go 都是流行且广泛使用的现代语言,但它们并不是真正的竞争对手,因为它们可以解决截然不同的用例。
Go 的整个编程方法与 Rust 完全不同,这些特性特别适合某些人,但也可能完全激怒其他人。这是有道理的,因为如果 Rust 和 Go 都以基本相似的方式解决基本相同的问题,为什么我们需要两种不同的语言?
那么,我们是否可以从 Rust 和 Go 的做法入手,解读它们各自的本质呢?我们一起来尝试一下吧。
垃圾收集
"垃圾收集,还是不垃圾收集"始终是一个没有正确答案的问题。总的来说,垃圾收集和自动内存管理可以帮助我们快速、轻松地开发可靠、高效的程序。所以对于一些开发者来说,这些都是必不可少的功能。
其他人则认为,垃圾收集及其性能开销和全局暂停可能会导致不可预测的运行时行为并引入不可接受的延迟。当然,这种说法是有道理的。
接近硬件
计算机编程的历史可以说是一个日益复杂的抽象发展过程。它允许程序员解决问题而无需过多关注底层硬件的实际运行方式。
这种设计使得程序更容易编写并且更可移植。但对于其他程序来说,访问硬件和精确控制程序的执行方式更为重要。
Rust的目标是让程序员"靠近硬件",重新获得更多的控制权;而 Go 则抽象了架构细节,让程序员能够更接近问题。
Golang 擅长编写微服务和典型的"DevOps"任务,但它不是一种系统编程语言。Rust 对于并发性、安全性和/或性能很重要的任务来说更强大;但它的学习曲线比 Go 更陡峭。
性能至上
事实上,对于大多数程序来说,性能不如代码可读性重要。但是,如果某些项目确实将性能放在第一位,那么 Rust 中的许多设计权衡将帮助您将代码的执行速度一路推向极限。
相比之下,Go 更关心代码的简单性,甚至愿意为此牺牲一些运行时性能。但 Go 的构建速度是无与伦比的,这对于大型代码项目来说往往更为重要。
Rust 的执行速度比 Go 更快。在基准测试中,Rust 确实更快,在某些情况下快了一个数量级。但在选择 Rust 之前,请明确一点:Go 在大多数基准测试中并没有落后太多,而且相对于 Java、C#、JavaScript 和 Python 等语言,它仍然保持着性能优势。
如果您需要一流的性能,请选择这两种语言中的任何一种,速度性能永远不会令人失望。另外,如果你正在构建一个处理高强度负载的Web服务,并且需要灵活的垂直/水平缩放,两种语言也都可以满足需求。
正确性
另一方面,如果你不强迫程序永远不会出错,那么权衡就会不同。大多数代码并不是为长期使用而设计的,但有些程序确实可以在生产环境中运行多年。
面对这些现实,可能值得投入一点额外的时间来开发并确保程序正确可靠地工作,而不会在未来带来沉重的维护负担。
Go 和 Rust 都可以帮助您编写正确的程序,但方式不同:Go 提供了出色的内置测试框架,而 Rust 则专注于通过借用检查器消除运行时错误。
明天要发布的代码,用Go;如果是未来五年必须保持稳定的代码,那就选择Rust。
虽然 Go 和 Rust 对于严肃的开发项目来说都足够好,但最好充分了解它们的各种功能和优势。
简而言之,其他人的想法并不重要:只有您可以决定哪种编程语言更适合您的团队和项目需求。
总结
希望这篇文章能帮助您了解 Rust 和 Go 各自的亮点。如果可能的话,你最好稍微体验一下这两种语言,因为它们在任何技术路径上都非常有用,即使对于业余编程爱好者来说也是如此。
但如果你只有时间认真学习一门语言,请务必弄清楚 Go 和 Rust 各自的专长和倾向后再做选择。
当然,编程语言知识只是成功软件工程师的一小部分。除了编程之外,工程师还必须精通设计、工程、架构、沟通和协作。只要每个人都能做好以下几件事,无论你选择哪种编程语言,你都将成为一名优秀的软件工程大师。