2024 年如何学习 Rust:掌握 Rust 编程的完整入门指南

Read this post in other languages:

您在考虑选择 Rust 作为下一门要学习的编程语言。 您已经知道编写代码意味着什么,并至少有一种编程语言(可能是 Python 或 JavaScript)的使用经验。 您经常听到别人谈论 Rust。 人们说它是一种现代的系统编程语言,可以带来安全性和高性能,并解决了其他编程语言(例如 C 或 C++)难以避免的难题。 有人提到 Rust 的受欢迎程度越来越高。 您经常会看到一些博文介绍 Google、Microsoft、Amazon 和该领域的其他大公司如何采用这种语言。 其他文章也指出这种语言在各行各业的使用率在不断提高。 但也有人说 Rust 这种语言并不容易学,因此您会担心自己是否能掌握它。

如果您在以上描述中找到了自己的影子,那么这篇文章就是为您准备的。 我写这篇文章的目的是解答您在接触 Rust 时可能遇到的所有问题。 我将先探讨学习 Rust 会为软件开发者带来哪些益处,并将 Rust 与其他竞争性编程语言进行比较。 然后,我将介绍需要大家记住的最重要的 Rust 功能和概念。 这些功能使 Rust 成为编程语言领域的重大发展。 了解了这些知识后,我将继续提供入门建议,为您提供教育资源(书籍、指南、教程和课程),并建议最有效的学习路径。 您在学习 Rust 时可能会遇到一些挑战,因此,我将指导您如何应对这些挑战。 最后,我将介绍 Rust 真正大放异彩的软件领域,并展示如何进军这些领域。

2024 年为什么要学习 Rust?

开发者调查表明,Rust 是 IT 行业中使用最多的 12 种编程语言之一。 调查数据显示,10–13% 的软件开发者经常使用 Rust。 更为重要的是,如果单看刚刚开始学习编程的人员的数据,学习 Rust 的人数占比达到 11–18%。 Rust 学习者是数据增长的强大推动力。 例如,开发者生态系统现状调查表明,Rust 在过去六年稳步增长,并且没有出现任何停滞的迹象:

请注意“可能采用”一列:Rust 是唯一达到两位数的语言!

开发者对 Rust 的赞赏也无可匹敌。 我从何处得知? StackOverflow 开发者调查提供了令人惊叹的证据:

  • Rust 仍然是开发者社区中最受推崇的语言,而且已连续多年(8 年? 9 年? 没人能记住!)获此殊荣。
  • 已经在使用 Rust 的开发者不想改用其他编程语言。

作为 Rust 开发者大会的常客,我可以证明大家对 Rust 的赞赏是显而易见的。 Rust 开发者热爱 Rust,并创建了最友好的社区之一让大家参与进来。

另一方面,据 StackOverflow 调查报告,过去几年的年薪中位数有所下降,但其他主流编程语言也出现了这种趋势。 尽管 Rust 在顶级和中等规模 IT 公司的应用越来越广泛,但我们还没有看到 Rust 被大量小公司采用,大规模采用可能会为就业市场带来更多的 Rust 空缺职位,并降低求职者如今面临的竞争压力(有关背景信息,请参阅这篇精彩的讨论)。

如果我们考虑到语言、功能和生态系统,就会立刻明白这些数字产生的根源。 Rust 的开发目的是同时提供内存安全性和高性能。 语言设计者做出的独特选择可以确保减少代码中的内存访问错误,从而降低出现安全漏洞的概率。 您为此付出的代价并不包括性能上的损失。 那么代价是什么呢? 就是开发者为了让 Rust 编译器相信其代码真正安全所花费的时间。 一旦得到编译器的认同,就万事大吉了。 内存安全性和性能极其重要:它们共同为软件解决方案使用者(在当今意味着每个人)提供了更加流畅的体验。 Rust 的标准库、其他基石库和工具也提升了开发者的体验。 例如,使用 Rust 开发高性能并发应用程序并不是什么大不了的事情,因为生态系统已经成熟,完全有能力支持此类任务。

开发者还非常赞赏 Rust 知识适用于广泛的技术领域和行业。 最新的 Rust 年度调查确定了以下领域:

  • 服务器端和其他后台应用程序
  • 云计算应用程序、服务和基础架构
  • 分布式系统。
  • 计算机网络。
  • 计算机安全。
  • 嵌入式开发。
  • 游戏开发。
  • Web 前端(包括 WebAssembly)。
  • 以及其他许多领域。

当然,Rust 不是这些领域中使用的唯一编程语言。 每个领域都有竞争者。 人们通常会将 Rust 与 C++ 或 Go 作比较,因为它们有很多共同点,但在各个方面都有不同之处,包括内存安全性保证、性能承诺、工具和库的可用性、语言简单性和行业采用情况。 虽然 Rust 在后三个类别中可能比较落后,但它的性能与 C++ 相当,并且可以更轻松地避免内存访问缺陷和构建没有错误的应用程序。

理解 Rust 的核心概念

我们从宏观层面了解一下 Rust 及其功能。 Rust 既不是面向对象的编程语言,也不是函数式编程语言。 它不使用类,也不直接支持面向对象的模式。 它可以将函数作为一类值进行操作,但与成熟的函数式语言(如 Haskell 或 OCaml)相比,这种能力有限。

通过函数、值和类型编写代码

采用 Rust 编写的程序以合并到模块中的函数集合形式进行组织。 函数会操作值。 值为静态类型,这意味着每个值或表达式在编译时都应当有指定的类型。 Rust 可以提供原始类型和复合类型(数组和结构体),其标准库还为值集合提供了许多额外的类型。 Rust 支持通用类型,这样可以避免提及特定类型,并提供更通用的定义。 Rust 还以方法集合(即函数)形式提供特征,可为特定类型实现这些特征。 Rust 可以利用特征实现与支持继承和多态性的面向对象的语言同等级别的软件抽象。

内存管理

Rust 的内存管理方法基于以下原则:Rust 编译器必须知晓代码中分配内存的确切位置、访问内存的位置和方式,以及不再需要内存的位置。 知晓这些信息后,便可直接在生成的代码中插入相应指令,从而控制内存访问并自动释放已分配的内存,因此可以避免其他语言容易出现的许多常见缺陷。 这种方式有别于自动内存管理(JavaScript、Python、Java 或 C# 会使用),后者会在运行时检测不再需要的内存片段并收集垃圾。 因此,Rust 可以节省在运行时执行相应算法所需的时间,并同时实现内存安全性和高性能。

为了能够推断内存访问的知识,Rust 对内存的操作设置了限制,并定义了严格的规则以确保正确性:

  • 每个内存片段都必须由单个变量所有 – Rust 的所有权模型便基于此概念。
  • 改变内存片段需要独占访问权限(而不是仅读取内存)。
  • Rust 允许创建对内存片段的可变和不可变引用(借用内存片段),但会使用借用检查器强制确保正确性(例如禁止多个可变引用)。
  • Rust 编译器会计算并检查程序中每个变量从创建到被丢弃(不再可访问)的生存期

编译器的要求可能过于严格。 这可能是大家经常遇到的困扰,特别是在学习语言时:Rust 编译器可能无法接受逻辑上正确的代码段。

为了使这些概念更容易理解一些,我们来讨论一下与以下 Python 程序对应的 Rust 程序:

def print_list(numbers):
   for number in numbers:
       print(str(number) + " ", end="")
   print()


def add_one(numbers):
   numbers.append(1)


def main():
   numbers = [1, 1, 1]
   print_list(numbers)
   add_one(numbers)
   print_list(numbers)


if __name__ == '__main__':
   main()

因此,我们有一个包含三个元素的内存片段(Python 的列表)。 我们打印该内存片段,再添加一个元素,然后再打印。 我们在这里从未提到任何类型。 Python 不需要在程序中进行任何内存管理,但必须在某些时间点分配和释放内存。 此外,我们可以轻松传递 numbers 列表,无需考虑内存访问控制。 

采用 Rust 编写的同样的代码则与之不同,不同之处不仅体现在语法方面,还体现在类型和内存管理的整体方式方面:

// 在这里,我们通过引用 (&) 来获取向量。
// 我们无权改变元素。
// 我们不获取所有权;我们只是借用。
fn print_vec(numbers: &Vec) {
   for number in numbers {
       print!("{} ", number);
   }
   println!()
}


// 在这里,我们通过可变引用 (&mut) 来获取向量。
// 我们现在可以改变元素和向量本身。
// 我们仍不获取所有权;我们只是借用。
fn add_one(numbers: &mut Vec) {
   numbers.push(1)
}


fn main() {
   let mut numbers = vec![1,1,1];
   // 我们传递一个引用
   print_vec(&numbers);
   // 我们传递一个可变引用
   add_one(&mut numbers);
   // 我们再次传递一个引用
   print_vec(&numbers);
}

您自己探索这两个代码段并找出它们之间的异同,这会对您很有启发。 即使您不了解 Rust,看一下这段代码也能让您对它有个大致的了解。

尽管不断传递引用,但 numbers 变量仍拥有分配的内存。 Rust 默认进行只读内存访问,需要明确指定写入访问。 Rust 还可以确保在对 print_vec 的第二次调用中最后一次使用后释放内存。 

以下是 add_one 函数的变体,它接管了向量的所有权,并导致整个程序不正确:

fn add_one_incorrect(mut numbers: Vec) {
   numbers.push(1)
}

问题出在哪? 调用 add_one_incorrect 函数后,numbers 变量不再占用内存;它的生存期已结束,因此我们无法打印任何内容! 下面的屏幕截图显示了我们遇到问题:

引入错误的版本之前,Rust 的借用检查器可以确保传递引用未带来任何问题。 引入错误后,这种方式不再可行。 此处的语言行为体现了如何对内存访问进行严格控制。

并发

并发是指系统能够同时或在重叠时段执行多个任务或进程,以提高效率和性能。 这一过程可以涉及在多个处理器上并行执行,或在单个处理器上交错执行,使系统能够同时处理多项操作并更有效地管理多项任务。

Rust 开发者经常用无所畏惧来形容 Rust 的并发性。 让人们形成这种观点的因素如下:

  • 所有权模型对并发线程间的数据共享添加了更多控制。
  • 引入不可变的数据结构简化了并发算法的实现,并有助于提高线程安全性。
  • Rust 中采用通过信道进行消息传递的方式,显著降低了共享状态并发的复杂性。
  • Rust 的生存期和内存管理方式通常使处理并发基元(例如锁、信号量或屏障)的代码更加优雅、更加安全。
  • 在很多情况下,Rust 采用的异步编程方法可以避免使用复杂的并发模式,使开发者能够编写出简洁而清晰的代码。

尽管并发并不是初学者接触 Rust 时最先学习的内容,但它仍比很多其他编程语言更容易掌握。 更为重要的是,Rust 可以帮助开发者编写出更不容易出错的并发代码。

如何开始使用 Rust

只需在计算机上安装两样东西便可开始使用 Rust:

  1. Rust 工具链 – 包含 Rust 编译器和其他实用工具的工具集合。
  2. 代码编辑器或 IDE(集成开发环境)。 

第一步非常简单 – 只需转到 rustup.rs 并运行系统建议的命令或下载安装程序即可(具体取决于操作系统)。

第二步需要做出选择。 您可以选择使用配置为提供 Rust 支持的代码编辑器(例如,Visual Studio Code 支持 Rust,但需要进行一些设置),也可以选择使用专用的 Rust IDE(例如 RustRover,它是一款可供任何 Rust 学习者免费使用的 JetBrains IDE)。

如果您选择 RustRover,则不需要进行任何配置。 您可以启动 RustRover,创建新项目(使用欢迎屏幕上的 New Project(新建项目)按钮),并运行默认生成的 Hello, world! 程序(使用装订区域中的绿色三角形图标运行 main 函数):

如果您遇到任何问题,请参阅 RustRover 的快速入门指南。 

如果要实现简单功能以外的任何其他功能,则需要添加外部依赖项。 Rust 项目依赖于软件包管理器 Cargo。 在 Rust 中,软件包被称为 crate。 依赖项是在 Cargo.toml 文件中指定的,例如:

[package]
name = "hello"
version = "0.1.0"
edition = "2021"

[dependencies]
chrono = "0.4.38"

向我们的依赖项添加 chrono Crate 后,便可在代码中使用它提供的功能,例如:

use chrono::{DateTime, Local};

fn main() {
   println!("Hello, world!");
   let local: DateTime = Local::now();
   println!("Today is {}", local.format("%A"));
}

在此程序中,我们获得了当前(本地)日期和时间,并将设置为一周中的某天,然后打印结果。 例如,运行此程序后,我们会得到:

Hello, world!
Today is Thursday

学习 Rust 中的基本语法、数据类型和控制结构(if-conditionals、loops 等)与学习可用的 crate 及其提供的功能可以同时进行。 学会运行 Rust 程序后,您便可以使用外部依赖项。 接下来,我们谈谈可以简化 Rust 学习过程的资源。

学习路径和资源

如果您学过外语,就会知道语言学习需要掌握各种技能,例如阅读、写作、听力和口语。 还需要通过不同类型的活动培养这些技能。 老师通常会鼓励大家读文章、看视频、听播客、尽量多说、在社交媒体上发表文章等。 学习编程语言也一样。 学习如何使用 Rust(或任何其他编程语言)进行编码时,您应当:

  • 阅读书籍、文档、博文、发布公告和社交媒体讨论(这些对于了解信息和背景至关重要)。
  • 观看技术视频博主发布的视频。
  • 探索代码示例(必然包括阅读和修改这些代码示例!)。
  • 编写代码,以完成练习。
  • 按照实践教程进行操作。
  • 从头开始开发简单的项目(这一点非常重要 – 基于项目的学习对于培养独立编码技能总会有一定的帮助)。
  • 甚至可以参与开源项目(总会有一些对初学者来说足够简单的东西 – 多问问就可以!)。

请注意,阅读编程方面的内容和编写代码之间应该保持平衡。 不亲自编写代码将无法掌握一门编程语言。 同时,不阅读书籍或其他扩展资料可能会导致对内部细节的理解相对肤浅;任何复杂的情况如果不借助外部帮助都可能变得非常难以解决(这没有问题,但会拖慢您成长为专业开发者的速度)。

当您编写代码时,务必要复制在外部编写的练习,同时还要遵循自己(或借用)的想法来开发简单的应用程序。 确保您的练习不仅限于掌握算法,还要教授语言功能和库功能。 在开发简单的应用程序时,您要学会选择最适合自己目标的语言功能或库。 这本身就是一项基本技能。

因此,成功学习的关键在于将所有方法结合起来。 下面是我收集的可以帮助您成功学习的资源。

Rust 书籍

有很多学习 Rust 的好书可供选择:

  • 《Rust 程序设计语言》是官方出版的书籍,其目标读者是 Rust 学习者,并会定期更新。 这本书在社区内被奉为圣经。 我还推荐这本书的另一个版本,该版本更具互动性,增加了测验、可视化内容和练习。 该版本由布朗大学研究员 Will Crichton、Gavin Gray 和 Shriram Krishnamurthi 编写。 此外,我还推荐观看 Will Crichton 的访谈,他在访谈中探讨了提升 Rust 学习者体验的实验。
  • 由 Tim McNamara(更广为人知的名字是 timClicks)编著的《Rust 实战》 – 我建议大家在所有平台上关注他)。
  • 由 Herbert Wolverson 编著的《Hands-on Rust》 – 这本书特别能够吸引那些重视基于项目的学习的读者(您还可以找到很多 Herbert 制作的关于各种 Rust 概念的免费视频;我强烈推荐大家观看)。
  • 由 Jon Gjengset 编著的《Rust for Rustaceans》,这本 Rust 书籍受到很多社区成员的高度赞赏。  
  • 由 Brenden Matthews 编著的 《Code Like a Pro in Rust》
  • 由 David MacLeod 编著的《Learn Rust in a Month of Lunches》
  • 经过几个月的 Rust 学习后,您应该看看 Mara Bos 的《Rust Atomics and Locks》。 这是一本介绍 Rust 并发背后的底层概念的杰作。

Rust 教程

对于那些更喜欢动手操作的学习者,我推荐以下附带练习的教程和课程:

YouTube 上的 Rust 学习资源

对于喜欢在 YouTube 上学习的 Rust 开发者,我建议关注下面几个频道:

  • Let’s Get Rusty – 我也不知道它有什么魔法,但这些视频看上就停不下来。
  • Jeremy Chone 非常善于讲解复杂的概念。
  • Chris Biscardi 谈论用 Rust 和 Bevy 框架开发游戏等问题。 对于任何人来说,制作一款游戏都不失为一个出色的项目!
  • Jon Gjengset – 在您开始学习 Rust 的前几年,可能很难理解他对技术流的深入介绍,但我建议您尽早观看! 

Rust 社区

当然还有很多学习资源,但这里不能全部列出。 好消息是,您永远不会停止学习 Rust,因为这门语言在不断发展。

常见的挑战和克服方法

学习 Rust 会充满挑战。 但您可以运用正确的策略克服这些困难并掌握这门语言。 以下是一些会对您有所帮助的提示:

  1. 理解所有权模型。Rust 的所有权模型包括所有权、借用和生存期等概念,对于初学者来说,这些概念往往最具挑战。 初学者可以先从简单示例入手,并多加练习。 着重理解 Rust 为何强制执行这些规则,而不是如何解决编译器错误。 
  2. 慢慢研究借用检查器。借用检查器可能会为大家带来很多困扰,因为它非常严格,并可能导致令人摸不着头脑的编译器错误。 当您遇到借用检查器问题时,先退一步分析 Rust 试图防止什么。 通过引用或克隆数据等方式进行试验(但尽量不要克隆全部数据!)。 不要害怕在 Reddit 或 Rust Community Discord 服务器等论坛上寻求帮助。 这对于理解借用检查器具体原理确实很有用。 例如,您可以看一看 Nell Shamrell-Harrington 给出的这段精彩解答
  3. 利用 Rust 的实用文档。Rust 是一种相对较新的语言,因此有些内容可能不像更成熟的语言那样简单。 参考公认的内容全面、编写精良的 Rust 文档。 Rust 社区也贡献了 Rust by Example 指南等非常棒的资源。
  4. 先从简单项目着手 。刚开始使用 Rust 时,它的复杂程度甚至会让学习者觉得自己连简单的项目也无法驾驭。 请先实现基本程序,然后逐步过渡到更为复杂的程序。 举例来说,简单项目包括通过 clap 构建命令行工具、编写简单的文件解析器,或使用 Rocket 等框架创建基本的 Web 服务器。
  5. 学习使用代码编辑器或 IDE。手动编写 Rust 代码很容易出错。 您可以借助工具实现代码补全、Lint 分析和格式设置。
  6. 参与 Rust 社区。学习一门新语言会让人感到孤独。 可以通过参与开源项目、加入侧重于 Rust 的聊天室或参与论坛的方式与 Rust 社区互动。 Rust 社区以热情帮助新人而著称。
  7. 从错误中学习 。Rust 的编译器非常严格,会让您觉得自己一直在与它作斗争。 请将每个编译器错误视为学习的机会。 Rust 的错误消息通常描述得非常详细,可以引导您找到正确的解决方案。 经过一段时间的磨炼,您会发现,在这些错误的帮助下,您的代码写得更好、安全性也更高。
  8. 多点耐心。面对 Rust,人们很容易感到垂头丧气。 请记住,Rust 的设计宗旨是安全、高效,因此需要学习一些复杂的概念。 必要时休息一下,不要害怕多次重温主题,直到您确信自己已经完全掌握为止。
  9. 加入 Rust 学习小组 。许多开发者都在学习 Rust,加入学习小组可以提供支持和动力。 寻找当地的聚会或在线学习小组,甚至可以与朋友共同学习。

掌握 Rust 需要大量时间,但一切付出都是值得的。 Rust 的功能(例如其内存安全性保证和性能)使其成为一种功能强大的语言,非常适合系统编程、Web 开发等应用。 坚持下去;您会发现 Rust 学习充满乐趣且大有回报。

使用 Rust 构建真实应用程序 

现在,我们来简单检查一下 Rust 是否适合构建真实应用程序。 我们将重点关注几个相关的技术领域,因为这几个领域的案例研究强调了 Rust 的优势并证实了其实际适用性。

Rust 在 Web 开发中的应用

Rust 生态系统非常适合后端 Web 开发。 许多框架和库都可以执行常规 Web 开发任务,例如 HTTP 请求路由、JSON 和表单处理、模板制作、数据库访问、身份验证和授权、日志记录和跟踪等,并具有可投入使用的性能。 我建议前往 AreWeWebYet? 网站查看详细信息和实用链接。 剧透一下,答案是肯定的。 

大多数用于 Rust 的 Web 框架都很容易上手,而且它们的文档非常精彩,部分原因是它们之间存在竞争。 例如,Actix Web 社区提供最新的优秀示例集。 我的同事 Khalid Abuhakmeh 编写了初学者教程,其中介绍了如何构建简单的 HTML Web 应用程序,该应用程序使用 Rocket(Rust 的另一个 Web 框架)作为后端。 我前面提到过的 Luca Palmieri 编写了《Zero To Production in Rust》一书,这本书可以帮助您成为 Web 后端开发者,他还致力于开发 Pavex,这是一个发展前景良好的新兴 Web 框架。 对于后一个项目,让人兴奋的一点是 Luca 在一系列进度报告中细致地记录了设计选择。 了解选择某种设计方法的原因一直都很吸引人。 请查看此 Web 框架比较来了解 Rust Web 框架是如何积极发展的。

Rust 还活跃在 Web 前端,不过可能还不能完全投入正式使用。 尽管如此,Rust 在 WebAssembly 以及 eguiDioxus 等框架方面取得的整体进展仍然令人印象深刻。

将 Rust 与其他编程语言结合使用

我想知道 Rust 设计者是否设想过 Rust 会成为那些为其他编程语言(尤其是 Python 和 JavaScript)开发工具和库的开发者的首选语言。 Rust 可以提供更好的性能,并有足够大的吸引力让其他语言生态系统的开发者来学习和应用。 

PyO3 项目使开发者可以通过 Rust 实现原生 Python 模块,并在 Rust 二进制文件中访问 Python。 通过利用 PyO3,Python 开发者可以极其高效地以 Rust 实现 Python 库。 可以采用相似的方法通过 WebAssembly 和 wasm-bindgen 连接 Rust 和 JavaScript。 

Astral 及其创始人 Charlie Marsh 证明,开发以光速运行的 Python 工具是可以实现的(当然,我们都知道这只是一种营销口号,但结果确实令人着迷)。 

使用 Rust 开发的 JavaScript 运行时 Deno 可以提供非常好的性能。 这不是 JavaScript 生态系统中仅有的示例。 甚至还有通过 Rust 实现的精选 JavaScript 工具集合。 

还可以在 Rust 和其他编程语言之间实现互操作性。

Rust 中的系统编程和嵌入式编程

毫无疑问,Rust 在系统编程方面大放异彩。 来自 Google 和 Microsoft 的演讲者证实,将 Rust 引入他们的代码库可以减少安全漏洞的数量、提高性能,软件开发团队的工作效率也可以得到保持,甚至有时会有所提高。 Amazon 不仅支持在 AWS 上进行 Rust 开发,还使用 Rust 直接实现自己的基础架构。 Cloudflare 是一家构建内容分发网络和其他网络基础架构的公司,他们在许多底层项目中依赖 Rust,并将其框架贡献到 Rust 生态系统。 Ferrous Systems 是一家为 rust-analyzer 开发提供支持的公司,这家公司还开发了 Ferrocene,后者是一种适用于任务关键型应用程序的认证 Rust 工具链。 与其他开发相结合使得 Rust 可用于汽车和航空航天工业。 例如,有报道称沃尔沃雷诺为其车载软件使用 Rust。

结论和后续行动

是时候开启您的 Rust 之旅了。 Rust 是一门优秀的工业级语言,并且可以提供丰富的学习资料以及对新手友好的社区。 虽然学习过程中会面临一些挑战,但鉴于其采用的独特核心概念,也有方式可以克服这些挑战。 成功掌握 Rust 后,就业市场和各种应用领域便会向您敞开大门。 

希望我提供的学习路径和资源对您的学习之路有所帮助。 我只能建议您提前设定学习目标:找到您要参与的开源项目,或者尽早为您的项目提出想法。 您会惊讶地发现,自己实现这一目标的速度如此之快。

希望本文能鼓舞您坚持不懈地学习 Rust!

本博文英文原作者:

Vitaly Bragilevsky

Vitaly Bragilevsky

image description

Discover more