Go与Rust的对比与分析

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 各自的专长和倾向后再做选择。

当然,编程语言知识只是成功软件工程师的一小部分。除了编程之外,工程师还必须精通设计、工程、架构、沟通和协作。只要每个人都能做好以下几件事,无论你选择哪种编程语言,你都将成为一名优秀的软件工程大师。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/89170.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【JMeter】常用线程组设置策略

目录 一、前言 二、单场景基准测试 1.介绍 2.线程组设计 3.测试结果 三、单场景并发测试 1.介绍 2.线程组设计 3.测试结果 四、单场景容量/爬坡测试 1.介绍 2.线程组设计 3.测试结果 五、混合场景容量/并发测试 1.介绍 六、稳定性测试 1.介绍 2.线程组设计 …

带着问题看SpringBoot

带着问题看SpringBoot 1、Spring容器具体是什么? 跟进run方法,context this.createApplicationContext(),得出容器是AnnotationConfigServletWebServerApplicationContext类。 SpringApplication.run(ServeroneApplication.class, args);…

如何提取视频的音频到手机?这个音频提取方法很简单

提取视频中的音频可以帮助您获得视频的声音部分,而无需观看整个视频。这对于那些只想听视频的声音或想将视频的声音与其他音频内容混合使用的人来说非常方便。此外,提取音频也可以为需要创建音频剪辑或混音的音频制作者提供帮助。那么怎么提取呢&#xf…

GFPGAN 集成Flask 接口化改造

GFPGAN是一款腾讯开源的人脸高清修复模型,基于github上提供的demo,可以简单的集成Flask以实现功能接口化。 GFPGAN的安装,Flask的安装请参见其他文章。 如若使用POSTMAN进行测试,需使用POST方式,form-data的请求体&am…

数字孪生技术对旅游行业能起到什么作用?

随着疫情对我们生活影响的淡化,旅游行业迎来了新的春天,暑期更是旅游行业的小高潮,那么作为一个钻研数字孪生行业的小白,本文就着旅游的话题以及对旅游的渴望带大家一起探讨一下数字孪生对智慧旅游发展的作用~ 数字孪生作为一种虚…

Git最简入门

文章目录 几个基本概念版本控制Git的由来分布式 vs 集中式GitSVN Git、GitHub、GitLab、GitWeb、Gitee的区别 动手进行版本控制初始化Git使用情景一:开发新项目使用情景二:在已有项目上开发设置代理 参考 几个基本概念 版本控制 在工作学习中&#xff…

大数据项目实战(Hadoop集群搭建)

一,搭建大数据集群环境 1.2 Hadoop集群搭建 1.2.1 jdk安装 1.下载jdk (1)在根目录下创建三个子目录以备后用。具体如下: mkdir -p /export/data mkdir -p /export/software mkdir -p /export/servers (2)下载路径: 1、官网下载地址http…

[docker][WARNING]: Empty continuation line found in:

报警内容: 下面展示一些 内联代码片。 //执行 sudo docker build ubuntu:v1.00 . [WARNING]: Empty continuation line found in:出现上述错误原因为18行多了一个 " \" 符号,去除即可

【网络教程】如何创建/添加钉钉机器人以及如何获取机器人的Token/Secret

文章目录 创建钉钉机器人添加钉钉机器人获取机器人的Token/Secret相关网站创建钉钉机器人 这里以PC端的操作为例,按照如下操作进行 访问 钉钉开放平台选择机器人选项卡,点击右上角的创建应用,这里会有一个弹窗,我这里选择的是继续使用旧版,如图按照要求填写相关信息创建自…

实现高效消息传递:使用RabbitMQ构建可复用的企业级消息系统

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 RabbitMQ是一个在 AMQP(高级消息队列协议)基…

什么是算法评价指标

在我们建立一个学习算法时,或者说训练一个模型时,我们总是希望最大化某一个给定的评价指标(比如说准确度Acc),但算法在学习过程中又会尝试优化某一个损失函数(比如说均方差MSE或者交叉熵Cross-entropy&…

短视频seo源码矩阵系统开源---代码php分享

前言:短视频seo源码 短视频seo矩阵系统源码私有化部署 短视频seo源码 短视频seo矩阵系统源码私有化怎么部署? 首先我们来给大家普及一下什么是短视频seo矩阵系统?视频矩阵分为多平台矩阵与一个平台多账号矩阵,加上seo排名优化&…

springboot整合rabbitmq发布确认高级

在生产环境中由于一些不明原因,导致 rabbitmq 重启,在 RabbitMQ 重启期间生产者消息投递失败,导致消息丢失,需要手动处理和恢复。于是,我们如何才能进行 RabbitMQ 的消息可靠投递。 发布确认 发布确认方案 架构 配置…

【Vue框架】基本的login登录

前言 最近事情比较多,只能抽时间看了,放几天就把之前弄的都忘了,现在只挑着核心的部分看。现在铺垫了这么久,终于可以看前端最基本的登录了😂。 1、views\login\index.vue 由于代码比较长,这里将vue和js…

有哪些前端调试和测试工具? - 易智编译EaseEditing

前端开发调试和测试工具帮助开发人员在开发过程中发现和修复问题,确保网站或应用的稳定性和性能。以下是一些常用的前端调试和测试工具: 调试工具: 浏览器开发者工具: 现代浏览器(如Chrome、Firefox、Safari等&#…

剪枝基础与实战(2): L1和L2正则化及BatchNormalization讲解

1. CIFAR10 数据集 CIFAR10 是深度学习入门最先接触到的数据集之一,主要用于图像分类任务中,该数据集总共有10个类别。 图片数量:6w 张图片宽高:32x32图片类别:10Trainset: 5w 张,5 个训练块Testset: 1w 张,1 个测试块Pytorch 集成了很多常见数据集的API, 可以通过py…

STM32 无法烧录

1. 一直显示芯片没连接上,检查连线也没问题,换了个ST-Link 烧录器还是连不上,然后又拿这个烧录器去其它板子上试下,就可以连接上,说明我连线没问题,烧录器也没问题,驱动什么的更是没问题&#x…

慕课网 Go工程师 第三周 package和gomodules章节

Go包的引入: 包名前面加匿名,只引入但不使用,如果对应包有init函数,会执行init函数(初始化操作) 包名前面加. 把这个包的结构体和方法导入当前包,慎用,你不知道当前包和被引入的包用…

WPF实战项目十二(API篇):配置AutoMapper

1、新建类库WPFProjectShared,在类库下新建文件夹Dtos,新建BaseDto.cs,继承INotifyPropertyChanged,实现通知更新。 public class BaseDto : INotifyPropertyChanged{public int Id { get; set; }public event PropertyChangedEv…

七大出海赛道解读,亚马逊云科技为行业客户量身打造解决方案

伴随全球化带来的新机遇和国内市场的进一步趋于饱和,近几年,中国企业出海快速升温,成为了新的创业风口和企业的第二增长曲线。从范围上看,出海市场由近及远,逐步扩张。从传统的东南亚市场,到成熟的北美、欧…