Match控制模式在很多语言都有相同的特性,Rust的特别之处在于Match模式和Enum、Option搭配使用产生的效果。
基本用法
如果匹配到的代码块比较简短,可以不用使用大括号,并且以逗号分隔。如果比较长,那么就需要使用大括号,并且逗号分隔符可以省略。
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
fn main() {
let p = Coin::Penny;
let n = Coin::Nickel;
value_in_cents(p);
value_in_cents(n);
}
上述代码中,value_in_cents的参数类型是Coin,而Coin的子类型的变量也可以作为value_in_cents的入参。之前说过,Enum可以理解为一组子类型的集合,所有子类型都可以代表父类型。所以任何一个子类型变量,都可以作为 value_in_cents 的参数。
使用大括号的情况:
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => {
println!("Lucky penny!");
1
}
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
绑定参数
Enum是可以添加类型的,Match的各个匹配项可以将Enum绑定的类型作为匹配项的参数。
#[derive(Debug)] // so we can inspect the state in a minute
enum UsState {
Alabama,
Alaska,
// --snip--
}
enum Coin {
Penny,
Nickel,
Dime,
// 这里添加了一个Enum类型
Quarter(UsState),
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter(state) => {
println!("State quarter from {:?}!", state);
25
}
}
}
fn main() {
let u = Coin::Quarter(UsState::Alabama);
value_in_cents(u);
}
上面代码中,UsState::Alabama 就成了 Coin::Quarter(state) 中的参数 state。
Match模式与Option搭配使用
Match模式与Option搭配使用,就能够实现非空判断。
我们尝试实现一个函数,包含逻辑:如果参数不为空,就+1,如果为空,就不做任何操作。
fn main() {
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
None => None,
Some(i) => Some(i + 1),
}
}
let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
}
plus_one函数就实现了这个功能。值得注意的是,match中的每个分支都使用了不带;的函数return语句。
使用Match模式的规则
第一个规则:Match需要覆盖所有的可能。
fn main() {
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
Some(i) => Some(i + 1),
}
}
let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
}
以上代码没有处理None的情况,所以编译会报错。
第二个规则:可以实现类似Default的效果。
如果需要变量的值,可以使用任意一个变量名来替代,比如:
fn main() {
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
Some(i) => Some(i + 1),
a => a,
}
}
let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
}
如果不需要变量的值,可以使用 _ 来表示
fn main() {
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
Some(i) => Some(i + 1),
_ => temp(),
}
}
let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
fn temp(){}
}
如果分支后面不需要执行任何代码
fn main() {
let dice_roll = 9;
match dice_roll {
3 => add_fancy_hat(),
7 => remove_fancy_hat(),
_ => (),
}
fn add_fancy_hat() {}
fn remove_fancy_hat() {}
}
以上是Match模式匹配变量的例子