match在Rust中是一个强大的控制流运算符。match允许一个值与一系列模式进行匹配,并执行成功匹配上的模式对应的代码。模式可以是字面值、变量名、通配符... 例:
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u8{
match coin {
Coin::Penny => 1,//只有一行要执行的代码时可省略`{}`,与下一个模式之间用`,`隔开
Coin::Nickel => 5,
Coin::Dime => {
println!("{}", 10);
10
}//在Rust中逗号在`{}`后以及最后一个时都可省略
Coin::Quarter => {
println!("{}", 25);
25
}
}
}
fn main() {
let value = value_in_cents(Coin::Nickel);
println!("{}", value);
}
绑定值的模式
匹配的分支可以是绑定到被匹配对象的部分值,因此可以从枚举的变体中提取值。例:
#[derive(Debug)]
enum UsState {
Alabama,
Alaska,
}
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1, //只有一行要执行的代码时可省略`{}`,与下一个模式之间用`,`隔开
Coin::Nickel => 5,
Coin::Dime => {
println!("{}", 10);
10
} //在Rust中逗号在`{}`后以及最后一个时都可省略
Coin::Quarter(state) => {//绑定值
println!("{:#?}", state);
25
}
}
}
fn main() {
let value = value_in_cents(Coin::Quarter(UsState::Alaska));
println!("{}", value);
}
匹配Option<T>
例:
//若传入的Option中有值则值+1,无值则返回None
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
Some(value) => Some(value + 1),
None => None,
}
}
fn main() {
let value = Some(666);
let r = plus_one(value);
let value1 = None;
let r1 = plus_one(value1);
println!("{:#?}, {:#?}", r, r1);
}
match必须穷举所有可能
对上一个例子中的plus_one函数做以下修改:
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
Some(value) => Some(value + 1),
}
}
编译器会给出以下错误提示:
error[E0004]: non-exhaustive patterns: `None` not covered
--> src\main.rs:3:11
|
3 | match x {
| ^ pattern `None` not covered
所以使用match时必须覆盖所有可能性,不然无法成功编译。若match分支较多,我们不想一一匹配处理,可使用_通配符来代替剩下的还没有列出的值。例:
fn main() {
let value = 6u8;
match value {
1 => println!("one"),
2 => println!("two"),
3 => println!("three"),
4 => println!("four"),
5 => println!("five"),
_ => (),
}//value是u8类型(0-255),但是我们只想处理1-5,
//所以除了1-5都会进入通配符_分支
}
if let
如果我们只想处理一种情况,可使用if let语法简化我们的代码。例:
fn main() {
let value = Some(6u8);
if let Some(6) = value {
println!("{:#?}", value);
}
}
此外还可搭配else、else if使用,例:
fn main() {
let value = Some(7u8);
if let Some(6) = value {
println!("6 => {:#?}", value);
} else if let Some(5) = value {
println!("5 => {:#?}", value);
} else {
println!("_ => {:#?}", value);
}
}