模式匹配(Pattern Matching) 是一种强大的控制流工具,主要用于解构数据结构、匹配值和控制程序分支。常见匹配结构有:
match
表达式if let
while let
for
循环- 函数参数解构
match
match是模式匹配的核心:
- 穷尽性检查:编译器强制要求处理所有可能情况。
- 模式顺序:按顺序匹配,首个匹配成功即执行对应分支。
_
匹配任何值,用于忽略不需要的值;..
忽略结构体 / 元组的部分字段;|
(管道符)实现或逻辑匹配,同时匹配多个;@
绑定,将匹配值绑定到变量;
- 返回值:每个分支的表达式结果必须是相同类型。
rust
match value {
pattern1 => expr1,
pattern2 => expr2,
_ => default_expr,
}
字面量模式
直接匹配具体的值(字面量),支持数字、字符串、布尔值等。
rust
let x = 3;
match x {
1 => println!("One"),
z @ (2 | 3) => println!("or-{}", z), // 多重匹配
z @ 4..=6 => println!("rang-{}", z), // 范围匹配
_ => println!("Other"), // 默认匹配
}
守卫模式
在模式后添加 if 条件
,进一步过滤匹配(仅当模式匹配且条件为真时生效)。
rust
let num = 8;
match num {
n if n % 2 == 0 => println!("Even: {}", n), // 8是偶数,匹配成功
n => println!("Odd: {}", n),
}
let pair = (2, 3);
match pair {
(x, y) if x + y == 5 => println!("Sum is 5"), // 2+3=5,匹配成功
_ => println!("Sum is not 5"),
}
引用模式
当模式中的值是引用类型时,需要注意 ref
和 ref mut
(否则会产生移动语义,原有变量的所有权会丢失):
rust
let tmp = &Some(10); // 临时值的引用
match tmp {
// Some(x) => println!("x = {}", x), // x为&i32
&Some(x) => println!("x = {}", x), // x为i32
_ => {}
}
所有权与引用
rust
// 引用类型
let rOne = Some(String::from("hello"));
match rOne {
Some(ref x) => println!("x = {}", x),
_ => {}
}
println!("rOne: {:?}", rOne);
// 所有权移动
let rTwo = Some(String::from("hello"));
match rTwo {
Some(x) => println!("x = {}", x),
_ => {}
}
// 此时rTwo已没有所有权,不能再打印
// println!("rOne: {:?}", rTwo);
可修改引用,对原值进行修改
rust
let mut a = Some(1);
match a {
Some(ref mut v) => *v += 10,
None => (),
}
println!("a = {:?}", a); // 输出 Some(11)
绑定
可以在匹配时绑定部分匹配值:
rust
enum Message { Hello { id: i32 } }
let msg = Message::Hello { id: 7 };
match msg {
Message::Hello { id: id_variable @ 3..=10 } => {
println!("id 在范围内: {}", id_variable);
}
Message::Hello { id } => {
println!("id 不在范围: {}", id);
}
}
复合结构匹配
结构体模式
可自动解构结构中的字段,
rust
struct Point { x: i32, y: i32 }
let p = Point { x: 10, y: 20 };
match p {
Point { x: 0, y } => println!("On y-axis at {}", y),
Point { x, y: 0 } => println!("On x-axis at {}", x),
Point { x, y } => println!("({}, {})", x, y),
// Point { x, .. } => println!("({}, -)", x), //不关心y
}
枚举模式
枚举是模式匹配的核心应用场景,用于匹配不同的枚举变体(Variant)。
rust
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
let msg = Message::Move { x: 5, y: 10 };
match msg {
Message::Quit => println!("Quit"),
// 解构结构体变体的字段
Message::Move { x, y } => println!("Move to ({}, {})", x, y), // 匹配成功
// 解构单值变体
Message::Write(s) => println!("Write: {}", s),
// 解构元组变体
Message::ChangeColor(r, g, b) => println!("Color: ({}, {}, {})", r, g, b),
}
切片模式
匹配切片或数组的结构(长度固定时可精确匹配,长度不固定时用 ..
匹配任意长度)。
rust
let arr = [1, 2, 3, 4];
// 匹配长度为4的数组,且首元素为1,末元素为4
match arr {
[1, a, b, 4] => println!("a={}, b={}", a, b), // a=2, b=3
_ => println!("Other"),
}
let slice = &[10, 20, 30];
// 匹配切片的开头和结尾,中间用 .. 匹配任意长度
match slice {
[first, .., last] => println!("First: {}, Last: {}", first, last), // First:10, Last:30
[] => println!("Empty slice"),
}
其他模式匹配
if let
当只需要处理一种匹配情况,其他情况忽略时使用
rust
let option = Some(5);
// 等价于 match option { Some(x) => ..., _ => () }
if let Some(x) = option {
println!("Got: {}", x); // 输出 "Got: 5"
}
while let
当需要反复匹配某个模式,直到不匹配时退出循环。
rust
let mut stack = vec![1, 2, 3];
// 每次弹出最后一个元素,直到栈为空
while let Some(top) = stack.pop() {
println!("Popped: {}", top); // 依次输出 3、2、1
}
for循环
在循环中解构迭代器的元素
rust
let pairs = vec![(1, "one"), (2, "two")];
// 解构元组 (数字, 字符串)
for (num, s) in pairs {
println!("{}: {}", num, s); // 输出 "1: one"、"2: two"
}