18.1 能用到模式匹配的地方18.1.1. 什么是模式模式pattern是 Rust 里一种特殊的语法用于匹配复杂类型和简单类型的结构。将模式与match表达式以及其他构造结合使用可以更好地控制程序的流程。模式由以下元素的一些组合构成- 字面值- 解构的数组、enum、struct和元组- 变量- 通配符- 占位符想要使用模式需要将它与某个值进行比较如果模式匹配就可以在代码中使用这个值的相应部分。18.1.2.match的分支Armarm分支可以使用模式。它的形式是match VALUE { PATTERN EXPRESSION, PATTERN EXPRESSION, PATTERN EXPRESSION, }match必须是穷尽的也就是说你必须覆盖所有可能的情况。match中也经常用到_通配符。它会匹配任何东西并且不会绑定到变量上。它通常用于match的最后一个分支或用于忽略某个值。如果想看更详细的介绍可以去 6.3. 控制流运算符-match。18.1.3.if let表达式if let表达式可以看作是只匹配一种可能性的match表达式。它还可以可选地包含-else if-else-else if let与match相比if let的缺点是不会检查穷尽性。如果我们省略了最后的else块从而漏掉对某些情况的处理编译器不会提醒我们可能存在逻辑错误。看个例子fn main() { let favorite_color: Optionstr None; let is_tuesday false; let age: Resultu8, _ 34.parse(); if let Some(color) favorite_color { println!(Using your favorite color, {color}, as the background); } else if is_tuesday { println!(Tuesday is green day!); } else if let Ok(age) age { if age 30 { println!(Using purple as the background color); } else { println!(Using orange as the background color); } } else { println!(Using blue as the background color); } }如果用户指定了最喜欢的颜色就用该颜色作为背景。如果没有指定最喜欢的颜色并且今天是星期二则背景颜色为绿色。否则如果用户把年龄指定为字符串并且我们能成功把它解析为数字则颜色为紫色或橙色具体取决于这个数值。如果这些条件都不适用则背景颜色为蓝色。这种条件结构让我们能够支持复杂的需求。使用这里写死的值时这个例子会打印Using purple as the background color。你可以看到if let也可以像match一样引入遮蔽变量if let Ok(age) age这一行引入了一个新的遮蔽变量age其中包含Ok里的值。这意味着在使用上面这种嵌套写法时我们需要把if age 30放在那个块里我们想与30比较的那个遮蔽后的age只在以{大括号开始的新作用域内有效。从 Rust 2024 edition 开始let chainslet链也允许把模式匹配和布尔条件写在同一个条件里例如if let Ok(age) age age 30此时Ok(age)绑定出的变量可以在同一条链的后续部分中使用。其余详细内容可见 6.4. 简单的控制流-if let。18.1.4.while let条件循环while let和if let有点相似只要模式继续匹配它就允许while循环一直运行。看个例子let mut stack Vec::new(); stack.push(1); stack.push(2); stack.push(3); while let Some(top) stack.pop() { println!({top}); }这个例子会依次打印 3、2、1。pop方法会从向量中取出最后一个元素并返回Some(value)。如果向量为空pop返回None。只要pop返回Somewhile循环就会继续运行其块中的代码。当pop返回None时循环停止。我们可以用while let把栈中的每个元素依次弹出。18.1.5.for循环for循环是 Rust 中最常见的循环。在for循环中模式就是紧跟在for关键字后面的那个值。在for循环中直接跟在关键字for后面的值是一个模式。例如在for x in y中x就是模式。下面的例子演示了如何在for循环中使用模式来解构元组let v vec![a, b, c]; for (index, value) in v.iter().enumerate() { println!({value} is at index {index}); }输出a is at index 0 b is at index 1 c is at index 2其余信息可见 3.6. 控制流循环。18.1.6.let语句let语句也是模式其语法是let PATTERN EXPRESSION;看个例子let (x, y, z) (1, 2, 3);我们将元组与模式进行匹配。Rust 会把值(1, 2, 3)与模式(x, y, z)比较并发现该值与模式匹配于是把1绑定到x把2绑定到y把3绑定到z。你可以把这个元组模式看成其中嵌套了三个单独的变量模式。18.1.7. 函数参数函数参数也可以是模式。看个例子fn foo(x: i32) { // ... }其中的x部分就是一个模式。正如我们对let所做的那样我们也可以在函数参数中把元组与模式进行匹配。例如fn print_coordinates((x, y): (i32, i32)) { println!(Current location: ({x}, {y})); } fn main() { let point (3, 5); print_coordinates(point); }