Rust Option
Rust 没有 null。如果一个值可能不存在,就直接在类型里用 Option 表达出来。刚开始你会觉得多了些繁文缛节,但它彻底堵住了一整类 bug:在其他语言里导致过无数次崩溃的“空引用”。
Option 长什么样
Section titled “Option 长什么样”Option 是一个有两个变体的枚举:
enum Option<T> { Some(T), // 有值 None, // 没有值}其实你已经见过它了:vector 的 .get() 和 HashMap 的 .get() 返回的都是 Option。
创建 Option
Section titled “创建 Option”fn main() { let has_value: Option<i32> = Some(5); let no_value: Option<i32> = None;
println!("{:?}", has_value); println!("{:?}", no_value);}输出:
Some(5)None用 match 处理 Option
Section titled “用 match 处理 Option”把值安全地取出来,靠的是 match。Rust 强制你处理两种情况,所以你不可能一不小心漏掉“值不存在”的情况:
fn main() { let age: Option<i32> = Some(30);
match age { Some(value) => println!("年龄是 {value}"), None => println!("没有填写年龄"), }}一个贴近实际的例子
Section titled “一个贴近实际的例子”fn find_user(id: u32) -> Option<&'static str> { if id == 1 { Some("Alice") } else { None }}
fn main() { match find_user(1) { Some(name) => println!("找到了:{name}"), None => println!("找不到这个用户"), }
match find_user(99) { Some(name) => println!("找到了:{name}"), None => println!("找不到这个用户"), }}输出:
找到了:Alice找不到这个用户找不到用户时,这个函数既不返回 null,也不抛出异常。它的返回类型本身就在告诉每个调用者:“这里可能什么也找不到。”而且编译器不会允许调用者忽略这种可能。
快捷写法:unwrap_or 和 unwrap
Section titled “快捷写法:unwrap_or 和 unwrap”简单的场景下,写一整个 match 可能有点大材小用。这里有几个快捷写法:
fn main() { let age: Option<i32> = None;
let value = age.unwrap_or(0); // 没有值时退回到 0 println!("{value}");}还有 .unwrap(),它直接把值给你,但如果是 None 就会 panic(程序崩溃):
let age: Option<i32> = Some(30);let value = age.unwrap(); // 这里没问题,因为 age 是 Some1. 第一个偶数
Section titled “1. 第一个偶数”写一个函数 fn first_even(numbers: &[i32]) -> Option<i32>,返回 slice 中的第一个偶数,如果没有就返回 None。对 [3, 7, 8, 10] 用 match 打印结果,对 [1, 3, 5] 用 .unwrap_or(0) 打印结果。提示:遍历 slice,一旦 n % 2 == 0 就 return Some(n);循环结束后返回 None。
查看答案
fn first_even(numbers: &[i32]) -> Option<i32> { for &n in numbers { if n % 2 == 0 { return Some(n); } } None}
fn main() { match first_even(&[3, 7, 8, 10]) { Some(n) => println!("第一个偶数:{n}"), None => println!("没有偶数"), }
let fallback = first_even(&[1, 3, 5]).unwrap_or(0); println!("使用默认值:{fallback}");}输出:
第一个偶数:8使用默认值:02. 查找一项设置
Section titled “2. 查找一项设置”创建一个存放设置的 HashMap,里面只有 "volume",值为 80。然后遍历键 "volume" 和 "brightness":如果值存在就打印出来,不存在就打印一条“未设置”的提示。提示:HashMap 的 .get(key) 返回 Option,所以可以直接对它 match。
查看答案
use std::collections::HashMap;
fn main() { let mut settings = HashMap::new(); settings.insert("volume", 80);
for key in ["volume", "brightness"] { match settings.get(key) { Some(value) => println!("{key} = {value}"), None => println!("{key} 未设置"), } }}输出:
volume = 80brightness 未设置Option<T>表示一个可能存在、也可能不存在的值:Rust 没有null。Some(value)里装着值;None表示什么都没有。match是处理这两种情况的安全方式,编译器不会让你漏掉其中任何一个。.unwrap_or(default)给你一个默认值;.unwrap()遇到None会 panic,要少用。
小测验
1. 对于可能缺失的值,Rust 用什么来代替 null?
2. 对 None 调用 .unwrap() 会发生什么?
3. 当 age 是 None 时,age.unwrap_or(0) 会做什么?
4. 为什么说 match 是从 Option 中取值的安全方式?
5. 本页提到的哪些方法本身就返回 Option?
得分: 0 / 5
- Option 枚举 — Rust 程序设计语言:官方教程解释 Rust 为什么用
Option而不用null,以及它相比空值的优势。 std::option— 标准库文档(英文):Option能做的所有事情的概览,包括map、and_then、is_some等常用方法。- Option 和 unwrap — 通过例子学 Rust:
match、unwrap以及什么时候会发生 panic 的简短可运行示例。 Option<T>— 标准库文档(英文):完整的方法列表,每个方法都附有可以直接复制的小例子。