简介
实际查询不一定总能找到对应的值。Rust 使用 Option<T> 表示这种可能性:Some(value) 表示值存在,None 表示值不存在。这样,缺失情况会成为类型的一部分,而不是用一个虚构的数字隐藏缺失状态,也不会因为缺失值而触发 panic。
你将完成一个小型库存报告程序。它需要处理找到库存和未找到库存的情况,区分已有但库存为零的记录与完全不存在的记录,并在只有值存在时才需要执行操作的场景中使用 if let。
匹配存在值和缺失值
在本步骤中,你将使用穷尽匹配处理可选查询结果,替换占位用的报告代码。
进入准备好的 Cargo 项目:
cd /home/labex/project/option-inventory
打开源文件:
nano src/main.rs
准备好的 find_stock 函数会返回 Option<u32>。现在可以先把尖括号理解为「可能包含 u32 的 Option」;稍后会学习如何使用带尖括号参数定义可复用类型。Some(12) 包含库存数量,而 None 完全不包含库存数量。
在准备好的查询代码末尾,_ => None 使用了通配模式 _。它表示「之前的匹配分支都没有匹配到的任意值」。通配符不会创建可用变量;它会有意忽略未匹配的值,并返回 None。
找到 report 函数中的占位 println!,将这一行替换为下面的匹配代码:
match find_stock(code) {
Some(count) => println!("{code}: {count} in stock"),
None => println!("{code}: not found"),
}
Some(count) 既可以识别存在的值,也会将其中的数字赋予局部名称 count。None 分支会明确处理缺失情况,因此该匹配覆盖了所有可能的 Option<u32> 值。
按 Ctrl+O 保存,按 Enter 确认,然后按 Ctrl+X 退出。运行程序前,先检查代码:
cargo check
看到 Finished,说明 Option 的两种情况都已覆盖。现在运行报告程序:
cargo run --quiet
你应该看到:
A1: 12 in stock
B2: 0 in stock
Z9: not found
最后一行来自 None;前两行来自 Some,其中包括 Some(0)。
区分零库存和缺失
在本步骤中,你将为已有但库存为零的记录设置单独的处理方式,而不是把零当成缺失。
Some(0) 和 None 表示不同的情况。Some(0) 表示查询找到了这条记录,但库存数量为零。None 表示该代码没有对应的记录。正因为存在这种区别,用 0 这样的占位值代替缺失状态并不安全。
再次打开源文件:
nano src/main.rs
在 report 函数的匹配代码中,将下面的分支添加到现有 Some(count) 分支的正上方:
Some(0) => println!("{code}: out of stock"),
匹配分支会从上到下依次检查。更具体的 Some(0) 模式必须放在 Some(count) 之前,因为后者这个更宽泛的模式也能匹配零。
保存并退出,然后运行程序:
cargo run --quiet
现在的输出应为:
A1: 12 in stock
B2: out of stock
Z9: not found
现在,每一行分别表示一种不同状态:有库存、记录存在但库存为空,或记录缺失。
仅在值存在时执行操作
在本步骤中,你将使用 if let 完成一项只有查询成功时才需要执行的任务。
当每种情况都需要不同的处理方式时,穷尽匹配 match 最合适。if let PATTERN = VALUE 则适用于另一种常见情况:当模式匹配时执行一个代码块,否则不执行任何操作。它是一种简洁的条件模式写法。
打开源文件:
nano src/main.rs
在 main 函数正上方添加下面的函数:
fn highlight_available(code: &str) {
if let Some(count) = find_stock(code) {
println!("{code}: {count} available for promotion");
}
}
该模式只有在值为 Some 时才会匹配成功,因此在花括号内可以使用 count。这里没有 else 代码块,因为此辅助函数有意不为 None 输出任何内容。
在 main 函数中,删除准备好的 highlight_available("C3"); 行开头的 //。保存并退出,然后检查并运行程序:
cargo check
cargo run --quiet
完整输出应为:
A1: 12 in stock
B2: out of stock
Z9: not found
C3: 5 available for promotion
第四行表明,if let 成功提取了 Some(5) 中的值,并且没有为缺失值凭空添加处理行为。
总结
你已经匹配了 Some 和 None,保留了 Some(0) 与缺失状态之间的区别,并在只有存在值时才需要执行操作的场景中使用了 if let。


