Rust 学习笔记 24:模式匹配详情 (Pattern Matching)
“Patterns are the ultimate way to deconstruct reality.”
我们在前面的章节已经频繁使用了 match 和 let。其实,模式 (Pattern) 在 Rust 中无处不在。
只要涉及到数据赋值或参数传递,几乎都有模式的身影。
1. 模式无处不在
除了 match 表达式,哪里还有模式?
if let:
1if let Some(x) = option_value { ... }
while let:
1while let Some(top) = stack.pop() { ... }
for 循环:
1for (index, value) in v.iter().enumerate() { ... }
let 语句:
1let (x, y, z) = (1, 2, 3);
函数参数:
1fn print_coordinates(&(x, y): &(i32, i32)) { ... }
2. Refutability (可反驳性)
模式分为两类:
- 不可反驳的 (Irrefutable):匹配任何可能的值。例如
let x = 5;中的x。 - 可反驳的 (Refutable):可能匹配失败。例如
if let Some(x) = a_value中的Some(x)(因为a_value可能是None)。
let 语句、函数参数、for 循环只接受不可反驳的模式。如果你试图用 let Some(x) = value;,编译器会报错,因为它不能处理 None 的情况。
3. 结构与解构 (Destructuring)
解构结构体:
1struct Point { x: i32, y: i32 }
2match p {
3 Point { x, y: 0 } => println!("On the x axis at {}", x),
4 Point { x: 0, y } => println!("On the y axis at {}", y),
5 Point { x, y } => println!("On neither axis"),
6}
解构枚举:
我们在 Option 和 Result 中已经见得多了。
忽略值:
_:忽略单个值。..:忽略剩余值。例如(first, .., last)。
4. 匹配守卫 (Match Guards)
有时候光靠模式匹配还不够,我们需要额外的条件判断。
1let num = Some(4);
2
3match num {
4 Some(x) if x < 5 => println!("less than five: {}", x),
5 Some(x) => println!("{}", x),
6 None => (),
7}
那个 if x < 5 就是 Match Guard。
5. @ 绑定
@ 允许我们在创建一个存放值的变量的同时,测试这个值是否匹配模式。
1match msg {
2 Message::Hello { id: id_variable @ 3..=7 } => {
3 println!("Found an id in range: {}", id_variable)
4 },
5 // ...
6}
如果不使用 @,我们要么只能测试范围(拿不到具体值),要么只能拿到值(不能在模式里直接测试范围)。@ 二者兼得。
6. 小结
第24篇笔记。
- 模式匹配是 Rust 表达力的核心之一。
- 解构 让我们能轻松拆解复杂数据。
- Match Guards 和 @绑定 为匹配提供了更细粒度的控制。
下一篇,我们将进入 高级特性 (Advanced Features)。Unsafe Rust? 高级 Trait? 高级类型? 准备好迎接黑魔法了吗?
练习题:
- 编写一个
match表达式,匹配一个(i32, i32)元组,要求:如果是(0, 0)打印原点;如果是(_, 0)打印在 X 轴;如果是(0, _)打印在 Y 轴;如果是 x == y 打印在对角线上(使用 Match Guard)。 - 尝试在
if let中使用@绑定。
思考题:
Rust 的模式匹配与 switch-case 的本质区别是什么?(提示:它是基于结构和值的匹配,还是仅仅是值的跳转?)
本文代码示例:
关注公众号:极客老墨
更多 AI 应用开发、工程实践和效率工具分享,欢迎扫码关注。
