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. 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
实现了很多的方法: