Rust学习笔记
潘忠显 / 2025-02-14
最近在学习 Rust,主要在看 doc。在这个页面做些笔记。
我不会搬运文档中直白的东西,主要分享一些相较其他语言比较新鲜的东西。
持续更新,感兴趣的同学可以关注。
0. 安装和帮助文档
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
上边这一条命令的安装 Rust 相关的所有东西,包括:
- rustc:编译器,用于编译 Rust 源代码。
- cargo:包管理器和构建系统,用于管理项目、依赖、构建、测试和发布。
- rustup:工具链安装和管理器,用于安装和管理不同版本的 Rust 编译器和工具链。
最后这个 rustup
中,还提供获取 Rust 本地文档的功能——其实只是调用了浏览器打开了 index 页面。本地内容跟 https://doc.rust-lang.org/stable/book/ 是一样的。
rustup doc --book
其他语言也有类似的文档,比如 Go 的 godoc
工具跟代码是一致的,Python 的 pydoc
(实际调用可能是 pydoc3.13
这样) 只能显示你已经安装的模块的文档,跟官网文档不一样。
1. 所有权Ownership
所有程序都必须管理运行时使用计算机内存的方式。
有些语言具有垃圾收集功能,可在程序运行时定期查找不再使用的内存;在其他语言中,程序员必须明确分配和释放内存。
Rust 没有采用以上两种方法,而使用第三种方法——所有权规则:它确保在任何给定时间,只有一个变量可以拥有某块内存的所有权。
具体地包含三条规则:
- 每个值都有一个所有者
- 每个值在任一时刻只能有一个所有者
- 当所有者离开作用域时,值会被丢弃删除
通过所有权系统管理内存,其中包含一组编译器检查的规则。如果违反任何规则,程序将无法编译。
堆栈
编译时检查
转移
let s1 = String::from("hello");
let s2 = s1; // s1 的所有权被转移给 s2
// s1 现在无效,不能再使用
2. Option 和 Some
之前有接触过 Java、Scala,其中也有 Some
和 Option
之类,但当时没有怎么理解。
这里恰好 Rust 文档里也有详细的描述,顺便仔细看了一下。
Option
是什么
在 Rust 中,Option
是一个非常核心的枚举类型,它用于表示一个值可能存在或不存在的情况。Option
的定义如下:
enum Option<T> {
Some(T),
None,
}
从上面的定义可以看到,Option
是一个带有泛型的枚举。其中,Some
是一个包含具体值的变体,而 None
则表示没有值。
let x: Option<i32> = Some(10);
上边的语句,表示有一个类型为 Option<i32>
的变量,它的值是 Some(5)
,表示这个 Option
包含了整数 5
。也可以赋值是 None
,表示没有值。
为什么需要 Option
Option
其实可以被视为对低级语言(如 C 语言)中指针的一种高级抽象和优化,可以减少空指针异常带来潜在问题,提供一种更安全的方式来处理可能不存在的值。
你可以显式地表示一个值可能存在(Some(T)
)或不存在(None
),编译器会强制你处理所有可能的情况,从而避免了空指针错误。
所谓的「编译器强制处理」,一方面要使用其中的值,必须先判断 Option 是个 Some;另一方面在使用 match
一个 Option 变量的时候,需要处理 Some 和 None —— 这个是 match 的特性。
下边代码,在编译的阶段就会报错,因为 None 没有被覆盖到。
fn main() {
let t = Some(5);
match t {
Some(value) => println!("Got a value: {}", value),
// None => println!("No value found"),
}
}
Some(var)
的方式绑定到某个变量上,结合 let if
语句,也可以带来更好的可读性。
fn main() {
let t = Some(5);
if let Some(user) = t {
println!("Found user: {:?}", user);
} else {
println!("No value found")
}
}
在上面的代码中,if let
表达式使得你只需要关心 Some
的情况,而对于 None
则可以忽略,从而写出简洁、优雅的代码。
区别于 Scala 中的 Option
实现
虽然 Rust 中的 Option
与 Scala 中的 Optional
在设计目的和使用方式上非常相似,但在具体实现由明显差异。
前边介绍了在 Rust 中,Option
是一个枚举类型。
而在 Scala 中,Option
是一个抽象类,有两个子类:Some
和 None
。三个类定义如下:
sealed abstract class Option[+A] extends Product with Serializable
case class Some[+A](value: A) extends Option[A]
case object None extends Option[Nothing]
两者都有个 Option
实现了很多的方法: