模式匹配
Rust的match非常强大。且有许多特别的用法。
|
匹配多个值。...
匹配一个范围(包含最后一个值)。- match中必须存在
_
。Rust的match强制进行穷尽性检查,必须覆盖所有的可能值 - 如果需要得到
|
或者...
匹配到的值,可以使用@
绑定变量。 - 使用ref关键字来得到一个引用。
例:简单示例
let day = 5;
match day {
0 | 6 => println!("weekend"), // 多值匹配
1 ... 5 => println!("weekday"), // 范围匹配
_ => println!("invalid"), // 任意匹配
}
例:范围匹配
let c = 'w';
match c {
'a' ... 'z' => println!("小写字母"),
'A' ... 'Z' => println!("大写字母"),
_ => println!("其他字符"),
}
例:匹配枚举
enum Direction {
East,
West,
North,
South,
}
fn main() {
let dire = Direction::South;
match dire {
Direction::East => println!("East"),
Direction::North | Direction::South => {
println!("South or North");
},
_ => println!("West"),
};
}
例:匹配值绑定到变量。
let x = 1;
match x {
e @ 1 ... 5 => println!("got a range element {}", e), // 绑定变量
_ => println!("anything"),
}
ref与mut ref
模式匹配过程中,被匹配命中的资源偶未实现Copy
的类型就会被的move掉。因此,原owner就不再持有其所有权。但是有些时候,我们只想要从中拿到一个变量的(可变)引用,而不想将其move出作用域,就需要使用ref
与ref mut
例:
let x = 5;
// copy值给r。
match x {
r => println!("Got a reference to {}", r),
}
// 借用值给r。
match x {
ref r => println!("Got a reference to {}", r),
}
例:
fn main() {
let x = String::from("hello");
match x {
// r => println!("Got a reference to {}", r), // 引发编译错误。x被move给了r。match后x就无法再被使用。
ref r => println!("Got a reference to {}", r), // 借用x的资源给r。match后r失效。x依然能用。
}
println!("{}",x);
// 打印:
// Got a reference to hello
// hello
}
解构
即将指定数据结构中的数据获取出来。
解构元组
let pair = (0, -2);
match pair {
(0, y) => println!("x is `0` and `y` is `{:?}`", y),
(x, 0) => println!("`x` is `{:?}` and y is `0`", x),
_ => println!("It doesn't matter what they are"),
}
解构枚举
enum Action {
Say(String),
MoveTo(i32, i32),
ChangeColorRGB(u16, u16, u16),
}
fn main() {
let action = Action::Say("Hello Rust".to_string());
match action {
Action::Say(s) => {
println!("{}", s);
},
Action::MoveTo(x, y) => {
println!("point from (0, 0) move to ({}, {})", x, y);
},
Action::ChangeColorRGB(r, g, _) => {
println!("change color into '(r:{}, g:{}, b:0)', 'b' has been ignored", r, g);
}
}
}
解构结构体
解构一个结构体:
struct Point {
x: i64,
y: i64,
}
let point = Point { x: 0, y: 0 };
match point {
Point { x, y } => println!("({},{})", x, y),
}
对结构体字段更灵活的解构:
match point {
Point { x: x1, y: y1} => println!("({},{})", x1, y1) // 直接声明解构字段的变量名称。
}
使用..
忽略字段:
match point {
Point { y, .. } => println!("y is {}", y),
}
match守卫
将if表达式可以放在match的模式之后。
例:
let x = 4;
let y = false;
match x {
4 | 5 if y => println!("yes"), // y为false,就算匹配到了4,也不会打印'yes'
_ => println!("no"),
}
也可以在解构后,对解构值进行条件判断,若通过判断才允许继续执行后面的语句。
enum Action {
Say(String),
MoveTo(i32, i32),
ChangeColorRGB(u16, u16, u16),
}
fn main() {
let action = Action::MoveTo(1,1);
match action {
Action::Say(s) => {
println!("{}", s);
},
Action::MoveTo(x, y) if x < 2 && y < 2 => {
println!("point from (0, 0) move to ({}, {})", x, y); // 打印!
},
Action::ChangeColorRGB(r, g, _) => {
println!("change color into '(r:{}, g:{}, b:0)', 'b' has been ignored", r, g);
}
_ => {
println!("do nothing");
}
}
// 打印:point from (0, 0) move to (1, 1)
}