【Rust自学】6.3. 控制流运算符-match
2026/7/23 18:48:05 网站建设 项目流程

6.3 控制流运算符-match

6.3.1. 什么是match

match允许一个值与一系列模式进行比较,并执行与匹配模式对应的代码。模式可以是字面值、变量名、通配符等等。

match表达式想象成一台硬币分类机:硬币沿着带有不同大小孔洞的轨道滑下,每枚硬币都会从它遇到的第一个合适的孔洞落下。同样地,一个值会依次经过match中的每个模式,当它“适合”第一个模式时,就会落入执行时要使用的关联代码块中。

6.3.2.match的实际应用

来看个例子:编写一个函数,接受一枚未知的美国硬币,并以类似计数机的方式判断它是哪种硬币,然后返回其价值(以美分为单位)。

enum Coin { Penny,// 1美分 Nickel,// 5美分 Dime,// 10美分 Quarter,// 25美分 } fn value_in_cents(coin: Coin) -> u8 { match coin { Coin::Penny => 1, Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter => 25, } }
  • match关键字后面跟着一个表达式,在本例中就是值coin。这看起来与if使用的条件表达式很像,但有一个很大的区别:if的条件必须是布尔值,而match可以处理任何类型。本例中coin的类型是我们在第一行定义的Coin枚举。

  • 接下来是花括号。花括号里有四个分支(英文叫arm),每个分支都由待匹配的模式和对应的代码组成。第一个分支Coin::Penny => 1,使用Coin::Penny作为模式。=>用来分隔模式和要运行的代码,这里要运行的代码就是值1,也就是返回1。不同分支之间用逗号分隔。

  • match表达式运行时,它会把match后面的表达式——这里是coin——从上到下依次与各个分支比较。如果某个模式与值匹配,就执行与该模式关联的代码;如果不匹配,就继续检查下一个分支。匹配成功的分支所对应的代码表达式会作为整个match表达式的值返回。
    例如,如果match匹配到5美分硬币,也就是Coin::Nickel,那么整个表达式的结果就是5。又因为match表达式是value_in_cents中的最后一个表达式,所以它的值——5——会作为函数的返回值。

  • 这里每个分支的代码都很简单,所以用=>就够了。但如果某个分支包含多行代码,就需要用花括号把这些行包起来。例如:

fn value_in_cents(coin: Coin) -> u8 { match coin { Coin::Penny => { println!("Lucky penny!"); 1 } Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter => 25, } }

6.3.3. 绑定值的模式

match的分支可以绑定到被匹配值的一部分,从而可以从枚举变体中提取值。

例如,一位朋友正在尝试收集全部50个州的25美分硬币。当我们按硬币类型对零钱分类时,还会标注每个25美分硬币关联的州名(美国州太多了,这里只写了Alabama和Alaska):

#[derive(Debug)] // 便于调试打印 enum UsState { Alabama, Alaska, } enum Coin { Penny, Nickel, Dime, Quarter(UsState), } fn value_in_cents(coin: Coin) -> u8 { match coin { Coin::Penny => { println!("Lucky penny!"); 1 }, Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter(state) => { println!("State quarter from {:?}!", state); 25 } } } fn main() { let c = Coin::Quarter(UsState::Alaska); println!("{}", value_in_cents(c)); }
  • 给代表25美分硬币的Coin变体关联一份数据,也就是上面的UsState枚举。

  • value_in_cents函数中,Quarter分支也需要相应调整。匹配模式从Coin::Quarter改成Coin::Quarter(state),意思是把Coin::Quarter关联的值绑定到变量state上,这样在后面的代码块中就可以使用这个关联值。
    有些情况下可能不需要Coin::Quarter关联的值。这时可以用通配符_表示不关心内容:Coin::Quarter(_)

  • main中先声明变量c,存的是Coin::Quarter(UsState::Alaska)。也就是说,它保存了Coin::Quarter变体,关联值是UsState::Alaska变体。然后调用value_in_cents

来看输出:

State quarter from Alaska! 25

6.3.4. 匹配Option<T>

来分析上一篇文章 6.2. Option枚举 最后的代码示例:

fn main() { let x: i8 = 5; let y: Option<i8> = Some(5); let sum = match y { Some(value) => x + value, // 如果 y 是 Some,则解包并相加 None => x, // 如果 y 是 None,则返回 x }; }
  • 如果y不是None,就解包,把Some关联的值绑定到value,并返回x + value
  • 如果yNone,就只返回x的值。

6.3.5.match必须穷尽

Rust要求match覆盖所有可能性,这样才能保证代码安全有效。

对上一段代码稍作修改:

fn main() { let x: i8 = 5; let y: Option<i8> = Some(5); let sum = match y { Some(value) => x + value, }; }

输出:

error[E0004]: non-exhaustive patterns: `None` not covered --> src/main.rs:5:21 | 5 | let sum = match y { | ^ pattern `None` not covered | note: `Option<i8>` defined here --> /Users/stanyin/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/option.rs:600:1 | 600 | pub enum Option<T> { | ^^^^^^^^^^^^^^^^^^ ... 604 | None, | ---- not covered = note: the matched value is of type `Option<i8>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | 6 ~ Some(value) => x + value, 7 ~ None => todo!(), |

Rust发现没有覆盖None这种可能性,所以报错。一旦补上处理None的分支,就没问题了。

如果可能性太多,或者你不想处理其中一些情况,可以使用通配符_

6.3.6. 通配符

先照常写出你想处理的分支,其余情况用通配符_代替。

例如:v是一个u8变量,我们想判断v是否为0

use rand::Rng; // 使用外部 crate fn main(){ let v: u8 = rand::thread_rng().gen_range(0..=255); // 生成随机数 println!("{}", v); match v { 0 => println!("zero"), _ => println!("not zero"), } }

u8有256种可能的值,用match自然不可能为每个值都写一个分支。因此可以为0写一个分支,其余情况用通配符_代替。

输出:

133 not zero

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询