Rust学习笔记(初级)

本文最后更新于:2023年3月1日 凌晨

Rust学习笔记(初级)

学习 Rust 语言是一个很有趣的过程,它是一门系统编程语言,被设计为安全、并发和快速的编程语言。我们可以按照以下计划一步步来学习 Rust 语言:

第一步:安装 Rust 和编辑器

首先,你需要安装 Rust 编程语言和一个代码编辑器。你可以从官方网站下载并安装 Rust 和 Cargo,Rust 的包管理工具。

安装 Rust 的方法非常简单,在终端或者命令提示符中输入以下命令:

1
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

接下来,你需要选择 Rust 的默认设置,这通常是安装 stable 版本。安装完成后,你可以通过以下命令检查 Rust 是否成功安装:

1
rustc --version

你还需要安装一个代码编辑器,比如 Visual Studio Code 或者 Sublime Text。选择一个你最喜欢的编辑器,并安装 Rust 插件,这样你就可以开始编写 Rust 代码了。

第二步:学习 Rust 的基本语法

在学习 Rust 的基本语法之前,你需要先了解一些 Rust 的基本概念。比如,Rust 中有许多关键字和符号,你需要熟悉它们的含义和用法。

学习 Rust 的基本语法通常包括以下几个方面:

  1. 变量和数据类型:了解 Rust 中的数据类型、变量声明和初始化。

  2. 运算符:了解 Rust 中的运算符,比如算术运算符、逻辑运算符和比较运算符。

  3. 控制流语句:了解 Rust 中的控制流语句,比如 if-else 语句、循环语句和 match 表达式。

  4. 函数和模块:了解 Rust 中的函数和模块的定义和用法。

  5. 所有权和借用:了解 Rust 中的所有权和借用,这是 Rust 最独特的特性之一。

在学习过程中,你可以通过 Rust 官方文档、Rust 程序设计语言(第二版)等资料来深入了解 Rust 的基本语法。同时,你也可以通过实践来巩固所学内容。

第三步:学习 Rust 的高级特性

学习完 Rust 的基本语法之后,你可以开始学习 Rust 的高级特性,比如并发编程、内存安全和宏。这些高级特性可以让你更好地利用 Rust 的优势来编写高质量的程序。

学习 Rust 的高级特性通常包括以下几个方面:

  1. 并发编程:了解 Rust 的并发编程模型和常用的并发编程模式。

  2. 内存安全:了解 Rust 的内存管理机制和所有权规则,以及如何避免常见的内存安全问题,如空指针和缓冲区溢出。

  3. 泛型编程:了解 Rust 中的泛型编程和 trait,以及如何使用它们来编写更灵活和可重用的代码。

  4. 宏:了解 Rust 的宏系统,以及如何使用宏来简化代码和提高代码的可读性。

在学习 Rust 的高级特性时,你可以通过阅读 Rust 官方文档、Rust By Example 等资料来深入了解。同时,你也可以尝试编写一些涉及这些高级特性的小程序来巩固所学内容。

第四步:实践项目

学习 Rust 之后,最好的方式就是实践。尝试编写一些小程序或者项目来巩固所学的内容。你可以从简单的程序开始,例如计算器或者简单的游戏,然后逐渐增加复杂度,挑战自己的技能。

你可以通过 Rust 社区提供的一些资源来找到一些适合的项目,例如 Rust 编程语言论坛和 Rust 库和框架列表。同时,你也可以自己设计一个项目,并根据需要引入 Rust 生态中的库和框架来实现它。

在实践项目的过程中,你可以遇到一些问题,这时你可以通过 Rust 社区提供的论坛和问答网站来获取帮助。

以上就是学习 Rust 的基本学习计划,现在我们开始执行学习计划。

第一步:安装 Rust

首先,你需要安装 Rust 工具链。请按照下面的步骤来安装:

  1. 访问 Rust 官网:https://www.rust-lang.org/zh-CN
  2. 点击页面中的 “安装” 按钮。
  3. 根据你的操作系统,选择相应的安装方式并按照说明进行安装。

安装完成后,可以通过运行下面的命令来检查 Rust 是否安装成功:

1
rustc --version

如果你看到了类似下面的输出,那么你已经成功安装了 Rust:

1
rustc 1.56.0 (a178d0322 2021-11-01)

第二步:了解 Rust 基本语法

在安装完 Rust 后,我们可以开始学习 Rust 的基本语法了。Rust 的语法比较严谨,但是也比较容易学习。下面是一些你需要学习的基本语法:

  1. 变量和数据类型:了解 Rust 中的基本数据类型,例如整数、浮点数、布尔值、字符等,以及如何声明和使用变量。

  2. 控制流语句:了解 Rust 中的条件语句和循环语句,例如 if、match、while、for 等,以及如何使用它们来控制程序流程。

  3. 函数和模块:了解如何定义和使用函数,以及如何组织代码成模块。

你可以通过 Rust 官方文档或者 Rust By Example 来学习这些基本语法。

下面是一些简单的 Rust 代码,可以帮助你入门:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 声明一个变量并赋值
let x = 42;

// 定义一个函数
fn add(x: i32, y: i32) -> i32 {
x + y
}

// 使用 match 控制流语句
let number = 5;
match number {
1 => println!("one"),
2 => println!("two"),
_ => println!("other"),
}

请尝试理解上面的代码,并编写一些简单的程序来巩固所学的基本语法。

第三步:深入学习 Rust 的高级特性

在学习 Rust 的基本语法后,你可以开始学习 Rust 的高级特性。这些特性包括:

  1. 所有权和借用:了解 Rust 的所有权和借用机制,以及如何使用它们来避免内存安全问题。

Rust 中的所有权和借用机制可以避免出现一些常见的内存安全问题,例如空指针引用、悬垂指针和多重释放等。所有权是 Rust 的一个核心概念,它确保了程序在运行时只有一个所有者拥有某个值。当这个所有者离开作用域时,这个值将被自动释放。借用机制则是一种机制,允许程序以只读或者可变的方式借用某个值的引用。

  1. 生命周期:了解 Rust 中的生命周期,以及如何使用生命周期来管理所有权和借用。

Rust 中的生命周期描述了一个值在程序中存在的时长。生命周期通常与借用有关,因为在 Rust 中,需要确保一个引用只能在其引用的值存在的时期内存在。

  1. Trait 和泛型:了解 Rust 中的 trait 和泛型机制,以及如何使用它们来编写更灵活和可重用的代码。

Trait 是 Rust 中的一种特殊类型,它描述了一个类型的行为。泛型则是一种通用的编程技术,它允许编写可重用的代码。Rust 中的 trait 和泛型机制结合在一起,可以让程序员编写更灵活和可重用的代码。

  1. 异常处理:了解 Rust 中的异常处理机制,以及如何使用它来处理异常情况。

Rust 中的异常处理机制包括 panic 和 Result 类型。panic 表示一个程序遇到了无法处理的错误,可以在代码中使用 panic! 宏来触发 panic。Result 类型则是一种包含一个值或一个错误的枚举类型,可以用来在函数调用之间传递错误信息。

你可以通过 Rust 官方文档、Rust By Example 或者 Rust Programming Language 这本书来深入学习 Rust 的高级特性。

请尝试理解这些高级特性,并编写一些程序来巩固所学内容。

第四步:安装 Rust

在学习 Rust 之前,你需要先安装 Rust 环境。Rust 支持多个操作系统,包括 Windows、Linux 和 macOS 等。下面是在不同操作系统下安装 Rust 的方法:

在 Windows 上安装 Rust

在 Windows 上安装 Rust,你需要执行以下步骤:

  1. 打开 Rust 官方网站

  2. 点击页面上的 “Download Rustup” 按钮,下载 Rustup 安装程序。

  3. 运行 Rustup 安装程序,按照提示进行安装。

  4. 安装完成后,打开命令行工具,输入 rustc --version 命令,检查 Rust 是否成功安装。

在 Linux 或 macOS 上安装 Rust

在 Linux 或 macOS 上安装 Rust,你需要执行以下步骤:

  1. 打开终端窗口。

  2. 执行以下命令,下载 Rustup 安装程序:

    1
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  3. 安装 Rustup,按照提示进行安装。

  4. 安装完成后,打开终端窗口,输入 rustc --version 命令,检查 Rust 是否成功安装。

安装 Rust IDE

安装好 Rust 后,你可以使用任何文本编辑器编写 Rust 程序,但使用一个好的 IDE 可以提高编码效率。这里介绍一些 Rust IDE:

  • Visual Studio Code:它是一个免费的开源代码编辑器,可以使用 Rust 插件来开发 Rust 程序。

  • IntelliJ IDEA:它是一个商业化的 IDE,可以使用 Rust 插件来开发 Rust 程序。

  • Rust-analyzer:它是一个轻量级的 Rust IDE,提供了代码自动补全、代码重构等功能。

现在,你已经安装好了 Rust 环境和 Rust IDE,可以开始编写 Rust 程序了。

下一步我们来学习 Rust 的基本语法。

第五步:学习 Rust 的基本语法

在学习 Rust 的基本语法之前,我们先简单介绍一下 Rust 的特点:

  • Rust 是一门静态类型的编程语言,意味着你需要在编译时指定变量类型,而不是在运行时。

  • Rust 采用所有权模型来管理内存,可以避免内存泄漏和野指针等问题。

  • Rust 采用模式匹配来处理控制流程,可以帮助开发者更好地组织代码逻辑。

接下来我们来学习 Rust 的基本语法:

变量和数据类型

在 Rust 中,你需要在声明变量时指定变量类型,否则编译器会报错。例如,下面是一个声明整数变量的示例:

1
let x: i32 = 10;

在这个例子中,变量 x 的类型是 i32,它的值是 10

除了整数类型,Rust 还支持其他的数据类型,包括浮点数、布尔类型、字符类型、字符串类型等。你可以使用 let 关键字来声明变量,例如:

1
2
3
4
let x: f32 = 3.14;
let y: bool = true;
let c: char = 'A';
let s: &str = "hello, world";

其中,f32 表示单精度浮点数,bool 表示布尔类型,char 表示字符类型,&str 表示字符串类型。

控制流程

在 Rust 中,你可以使用 if/elseloopwhilefor 等关键字来控制程序的流程。例如,下面是一个使用 if/else 的示例:

1
2
3
4
5
6
7
8
let x = 10;
if x > 0 {
println!("x is positive");
} else if x < 0 {
println!("x is negative");
} else {
println!("x is zero");
}

在这个例子中,我们使用 if/else 来判断变量 x 的值,并输出相应的信息。

函数

在 Rust 中,你可以使用 fn 关键字来定义函数。例如,下面是一个计算斐波那契数列的函数:

1
2
3
4
5
6
7
fn fib(n: i32) -> i32 {
if n <= 1 {
1
} else {
fib(n - 1) + fib(n - 2)
}
}

在这个例子中,函数名为 fib,它接受一个 i32 类型的参数 n,返回一个 i32 类型的值。函数内部使用递归的方式计算斐波那契数列。

结构体和枚举类型

在 Rust 中,你可以使用结构体和枚举类型来组织复杂的数据结构。结构体用于组织一组相关的数据,例如:

1
2
3
4
5
6
7
struct Point {
x: f32,
y: f32,
}

let origin = Point { x: 0.0, y: 0.0 };
let point = Point { x: 1.0, y: 2.0 };

在这个例子中,我们定义了一个名为 Point 的结构体,它包含两个 f32 类型的字段 xy。我们使用 let 关键字来创建一个 origin 的变量,它的值是 { x: 0.0, y: 0.0 }。我们还创建了一个 point 的变量,它的值是 { x: 1.0, y: 2.0 }

枚举类型用于定义一组可能的值,例如:

1
2
3
4
5
6
7
enum Color {
Red,
Green,
Blue,
}

let color = Color::Red;

在这个例子中,我们定义了一个名为 Color 的枚举类型,它包含三个可能的值 RedGreenBlue。我们使用 let 关键字来创建一个 color 的变量,它的值是 Color::Red

Trait

Trait 是 Rust 中的一种特殊类型,它用于定义一组行为或功能,可以被多个类型实现。类似于其他语言中的接口,Trait 可以让你定义一组方法,并在多个类型之间共享这些方法。

例如,下面是一个定义 Animal Trait 的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
trait Animal {
fn make_sound(&self);
}

struct Dog;
struct Cat;

impl Animal for Dog {
fn make_sound(&self) {
println!("woof");
}
}

impl Animal for Cat {
fn make_sound(&self) {
println!("meow");
}
}

在这个例子中,我们定义了一个 Animal Trait,它包含一个 make_sound 方法。我们还定义了两个类型 DogCat,它们都实现了 Animal Trait,并分别实现了自己的 make_sound 方法。

现在我们已经学习了 Rust 的基本语法,接下来我们将会学习 Rust 的高级特性。

所有权和生命周期

在 Rust 中,每个值都有一个所有者(owner),只有所有者才能控制这个值的生命周期。当所有者超出作用域或被显式释放时,与之关联的值将被销毁。

例如:

1
2
3
4
fn main() {
let s = String::from("hello");
println!("{}", s);
}

在这个例子中,我们创建了一个 String 类型的变量 s,并在 println! 宏中使用了它。在 println! 宏执行完毕后,s 的所有权会被释放,String 类型的值也会被销毁。

为了避免所有权问题,Rust 引入了引用(reference)的概念。引用是一个指向值的指针,它不拥有这个值,只是对它进行了借用。引用通过 & 符号来创建,例如:

1
2
3
4
5
6
7
8
9
fn main() {
let s = String::from("hello");
let len = calculate_length(&s);
println!("The length of '{}' is {}.", s, len);
}

fn calculate_length(s: &String) -> usize {
s.len()
}

在这个例子中,我们定义了一个名为 calculate_length 的函数,它接收一个 String 类型的引用,并返回它的长度。在 main 函数中,我们首先创建了一个 String 类型的变量 s,然后调用 calculate_length 函数并将它的引用作为参数传递。在 calculate_length 函数中,我们使用 s.len() 方法来计算字符串的长度。

在这个例子中,我们避免了将 String 类型的所有权传递给函数的问题,因为函数只是对它进行了借用,而不是拥有它。

在 Rust 中,引用还有一个生命周期(lifetime)的概念。生命周期用于定义引用的有效期,确保引用不会超出它所指向的值的生命周期。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fn main() {
let string1 = String::from("long string is long");

{
let string2 = String::from("xyz");
let result = longest(string1.as_str(), string2.as_str());
println!("The longest string is '{}'", result);
}
}

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}

在这个例子中,我们定义了一个 longest 函数,它接收两个引用 xy,它们的生命周期被定义为 'a。在函数体中,我们比较了这两个引用所指向的字符串的长度,并返回了长度更长的那个字符串的引用。

这里使用了生命周期的概念来确保 longest 函数返回的引用的生命周期不会超出 xy 引用所指向的字符串的生命周期。这是因为在函数返回时,函数内部的 string2 变量已经超出了作用域,对应的 String 类型的值已经被销毁。因此,返回的字符串引用必须要确保不会超出 string1string2 的生命周期范围。

在 Rust 中,生命周期可以通过以下几种方式来注明:

  • 'a:表示一个名为 'a 的生命周期。
  • &'a:表示一个引用,它的生命周期为 'a
  • &'a mut:表示一个可变引用,它的生命周期为 'a

为了正确使用生命周期,我们需要理解它们的关系和作用域,并通过合适的方式进行注明和管理。

提问

  1. Rust 中的所有权和引用有什么作用?
  2. 生命周期是什么?在 Rust 中如何注明生命周期?
  3. 如何避免所有权问题?可以给出一个例子说明吗?

第四部分:高级主题

在前面的学习中,我们已经学习了 Rust 中的基本语法、所有权、生命周期、模块化和并发编程等知识。在本节,我们将继续学习 Rust 中的高级主题。

1. 泛型和 trait

泛型和 trait 是 Rust 中非常重要的概念,它们可以帮助我们编写可重用的代码,从而减少重复的工作量。

泛型是指使用参数化类型来编写通用代码的技术。例如,可以使用泛型实现一个通用的栈结构,该栈可以存储任何类型的值。在 Rust 中,使用 <T> 来声明泛型类型,并在函数定义中使用它。

Trait 是一种类似于接口的概念,它定义了一组方法的集合,用于描述类型的行为。Trait 可以被用来限定泛型参数的类型,从而实现对类型进行约束。在 Rust 中,可以使用 impl Trait 来实现一个 trait,使得一个类型能够拥有这些方法。

提问

  1. 什么是泛型?如何在 Rust 中使用泛型?
  2. 什么是 trait?如何在 Rust 中定义和使用 trait?

2. 宏

宏是 Rust 中非常有用的一种功能,它可以让程序员编写自己的代码生成器。宏可以分为两种:声明式宏和过程式宏。

声明式宏是一种基于模式匹配的宏,它的输入是一段 Rust 代码,输出是一段 Rust 代码。通过这种方式,可以实现类似于函数调用的语法,但是在编译时会生成相应的代码。

过程式宏是一种基于编译器的 API 的宏,它可以用于在编译时对 Rust 代码进行操作。过程式宏可以分为三种:自定义派生宏、函数宏和属性宏。每种过程式宏都有不同的应用场景和优势。

提问

  1. 什么是宏?宏可以用来做什么?
  2. 声明式宏和过程式宏有什么区别?Rust 中有哪些类型的过程式宏?

3. Unsafe Rust

虽然 Rust 是一个安全的语言,但有时候我们需要使用一些不安全的操作,例如对内存进行操作、绕过借用规则等等。为了支持这种操作,Rust 提供了 unsafe 关键字。

在 Rust 中,unsafe 关键字用于标记不安全的代码块,这样编译器就会关闭一些检查和限制。使用 unsafe 关键字编写的代码需要特别小心,因为这些代码可以造成内存泄漏、段错误等的问题,而且可能会导致安全漏洞。

在使用 unsafe 代码时,需要遵循一些规则和最佳实践,例如避免未定义行为、正确处理指针、保证数据的同步和并发安全等等。

提问

  1. 什么是 unsafe 关键字?它用于标记什么样的代码块?
  2. 使用 unsafe 代码需要注意什么?在使用 unsafe 代码时需要遵循哪些规则和最佳实践?

4. FFI

FFI(Foreign Function Interface)是一种机制,可以让不同的语言之间进行交互。Rust 提供了强大的 FFI 支持,可以与其他语言进行无缝集成。

在 Rust 中,可以使用 extern 关键字声明一个外部函数,从而使其可以被其他语言调用。同时,还可以使用 #[no_mangle] 属性来防止 Rust 编译器重命名函数名称。另外,Rust 还提供了 C 兼容的数据类型和 API,从而使得与 C 语言的交互变得非常方便。

提问

  1. 什么是 FFI?为什么需要 FFI?
  2. 在 Rust 中如何使用 FFI?Rust 提供了哪些机制来方便与其他语言进行交互?

5. 生命周期和内存模型

在 Rust 中,所有权和生命周期是管理内存的关键概念。通过这些机制,Rust 确保程序运行时的内存安全和正确性。

在 Rust 中,内存被分为堆和栈。堆是用于存储动态分配的数据的区域,而栈是用于存储局部变量和函数参数的区域。Rust 通过所有权和生命周期来管理堆和栈中的内存。

所有权是指对于任何一个值,都有一个拥有它的变量。当该变量超出作用域时,它所拥有的值就会被自动释放。生命周期是指值存在的时间,它决定了值在内存中的存活时间。

通过生命周期和所有权的机制,Rust 可以避免许多内存相关的问题,例如空指针、野指针、内存泄漏等等。

提问

  1. 在 Rust 中,内存被分为哪两种类型?每种类型分别用来存储什么样的数据?
  2. 所有权和生命周期是如何管理内存的?它们有什么优势?

6. 并发编程

并发编程是现代计算机科学中非常重要的话题之一。在 Rust 中,可以使用线程和通道来实现并发编程。

线程是一种执行路径,它可以让程序同时执行多个任务。

在 Rust 中,可以使用标准库中的 std::thread 模块来创建线程。通过 std::thread::spawn 函数,可以创建一个新的线程并启动它的执行。同时,还可以使用 std::sync 模块提供的互斥锁和条件变量来实现线程之间的同步和通信。

除了线程和通道,Rust 还提供了一种更加高级的并发编程模型,即 async/awaitasync/await 是一种基于协程的并发编程模型,它允许在单个线程上同时执行多个异步任务,并通过 await 关键字来实现非阻塞式的等待。

提问

  1. 什么是线程?如何在 Rust 中创建和启动线程?
  2. Rust 中如何实现线程之间的同步和通信?
  3. 什么是 async/await?它是如何实现并发编程的?

实践项目

在学习 Rust 语言的过程中,最好的方式就是尝试实现一些实际的项目。以下是一些适合初学者尝试的 Rust 项目:

  1. Web 应用程序:使用 Rust 和一些流行的 Web 框架(例如 actix-web)构建一个 Web 应用程序,实现用户认证、数据存储和页面渲染等功能。

  2. 命令行工具:使用 Rust 编写一个命令行工具,实现文件操作、系统管理等功能。

  3. 游戏:使用 Rust 和一些游戏引擎(例如 amethyst)构建一个简单的 2D 或 3D 游戏。

  4. 系统编程:使用 Rust 编写一些系统级别的程序,例如操作系统、文件系统或网络协议等。

以上是一些适合初学者尝试的 Rust 项目,你可以根据自己的兴趣和实际情况选择其中的一个或多个进行实践。实践过程中,可以结合本教程中的知识点,不断地学习和探索 Rust 语言的各种特性和用法。

当你完成了一个项目之后,可以考虑将其发布到 Rust 社区中,以便其他人也可以使用和学习。以下是一些 Rust 社区中的项目发布平台:

  1. crates.io:Rust 社区中最流行的项目发布平台,类似于 Node.js 的 npm 和 Python 的 PyPI。

  2. GitHub:一个流行的代码托管和版本控制平台,可以将你的 Rust 项目发布到 GitHub 上,并通过 GitHub Pages 构建和部署文档。

  3. GitLab:类似于 GitHub 的另一个代码托管和版本控制平台。

  4. Launchpad:一个 Ubuntu Linux 发行版使用的软件包构建和发布平台,可以用于发布 Rust 项目的 Ubuntu 软件包。

  5. AUR:一个 Arch Linux 社区维护的软件包构建和发布平台,可以用于发布 Rust 项目的 Arch Linux 软件包。

以上是一些 Rust 项目发布平台,你可以根据自己的需求和偏好选择其中的一个或多个进行使用。

另外,参与 Rust 社区中的开源项目也是一个非常好的学习 Rust 的方式。在 Rust 社区中,有许多优秀的开源项目,例如 Rust 标准库、Rust 编译器、Cargo 等。通过参与这些项目的开发和维护,可以学习到 Rust 的最佳实践、代码规范和工具链等方面的知识。

提问

  1. Rust 社区中最流行的项目发布平台是什么?如何将 Rust 项目发布到这个平台上?
  2. Rust 社区中有哪些优秀的开源项目?如何参与这些项目的开发和维护?

总结

本教程介绍了 Rust 语言的基本语法、数据类型、控制结构、函数和模块、错误处理、面向对象编程、泛型、迭代器和闭包、并发编程以及实践项目等方面的知识。通过学习本教程,你应该可以掌握 Rust 语言的基础知识,并能够使用 Rust 编写一些实际的项目。

当然,Rust 语言的学习是一个持续不断的过程。在实践过程中,你会遇到许多问题和挑战,需要不断地学习和探索。同时,也要多参与 Rust 社区中的讨论和活动,结识更多的 Rust 爱好者和开发者,共同推动 Rust 语言的发展和应用。

祝你学习愉快!


Rust学习笔记(初级)
https://jinbilianshao.github.io/2023/02/16/Rust学习笔记(初级)/
作者
连思鑫
发布于
2023年2月16日
许可协议