Rust学习教程22 - 全模式列表

本文详细介绍了Rust中的全模式列表,包括匹配字面值、命名变量、单分支多模式、值的范围匹配、解构值、忽略模式中的值及匹配守卫等。通过实例展示了如何在匹配表达式中使用这些模式,如解构结构体、枚举、元组,以及如何通过匹配守卫设置额外条件。此外,还讨论了如何在模式中忽略和绑定值,帮助开发者更好地理解和运用Rust的模式匹配特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文节选自<<Rust语言圣经>>一书
欢迎大家加入Rust编程学院,一起学习交流:
QQ群:1009730433

全模式列表

在本书中我们已领略过许多不同类型模式的例子. 本节的目标就是把这些模式语法都罗列出来,方便大家检索查阅。

匹配字面值

let x = 1;

match x {
   
   
    1 => println!("one"),
    2 => println!("two"),
    3 => println!("three"),
    _ => println!("anything"),
}

这段代码会打印 one 因为 x 的值是 1。如果希望代码获得特定的具体值,则该语法很有用。

匹配命名变量

match一章中,我们有讲过变量覆盖的问题,这个在匹配命名变量时会遇到:

fn main() {
   
   
    let x = Some(5);
    let y = 10;

    match x {
   
   
        Some(50) => println!("Got 50"),
        Some(y) => println!("Matched, y = {:?}", y),
        _ => println!("Default case, x = {:?}", x),
    }

    println!("at the end: x = {:?}, y = {:?}", x, y);
}

让我们看看当 match 语句运行的时候发生了什么。第一个匹配分支的模式并不匹配 x 中定义的值,所以代码继续执行。

第二个匹配分支中的模式引入了一个新变量 y,它会匹配任何 Some 中的值。因为我们在 match 表达式的新作用域中,这是一个新变量,而不是开头声明为值 10 的那个 y。这个新的 y 绑定会匹配任何 Some 中的值,在这里是 x 中的值。因此这个 y 绑定了 xSome 内部的值。这个值是 5,所以这个分支的表达式将会执行并打印出 Matched, y = 5

如果 x 的值是 None 而不是 Some(5),头两个分支的模式不会匹配,所以会匹配模式_。这个分支的模式中没有引入变量 x,所以此时表达式中的 x 会是外部没有被覆盖的 x

一旦 match 表达式执行完毕,其作用域也就结束了,同理内部 y 的作用域也结束了。最后的 println! 会打印 at the end: x = Some(5), y = 10

如果你不想引入变量覆盖,那么需要使用匹配守卫(match guard)的方式,稍后在匹配守卫提供的额外条件中会讲解。

单分支多模式

match 表达式中,可以使用 | 语法匹配多个模式,它代表 的意思。例如,如下代码将 x 的值与匹配分支相比较,第一个分支有 选项,意味着如果 x 的值匹配此分支的任何一个模式,它就会运行:

let x = 1;

match x {
   
   
    1 | 2 => println!("one or two"),
    3 => println!("three"),
    _ => println!("anything"),
}

上面的代码会打印 one or two

通过序列..= 匹配值的范围

数值类型中我们有讲到一个序列语法,该语言不仅可以用循环中,还能用于匹配模式。

..= 语法允许你匹配一个闭区间序列内的值。在如下代码中,当模式匹配任何在此序列内的值时,该分支会执行:

let x = 5;

match x {
   
   
    1..=5 => println!("one through five"),
    _ => println!("something else"),
}

如果 x 是 1、2、3、4 或 5,第一个分支就会匹配。这相比使用 | 运算符表达相同的意思更为方便;相比 1..=5,使用 | 则不得不指定 1 | 2 | 3 | 4 | 5。相反指定序列就简短的多,特别是在希望匹配比如从 1 到 1000 的数字的时候!

序列只允许用于数字或字符类型,因为编译器会在编译时检查序列不为空。字符和数字值是 Rust 仅有的可以判断范围是否为空的类型。

如下是一个使用字符类型序列的例子:

let x = 'c';

match x {
   
   
    'a'..='j' => println!("early ASCII letter"),
    'k'..='z' => println!("late ASCII letter"),
    _ => println!("something else"),
}

Rust 知道 c 位于第一个模式的序列内,并会打印出 early ASCII letter

解构并分解值

也可以使用模式来解构结构体、枚举、元组和引用。

解构结构体

下面代码展示了如何用let解构一个带有两个字段 xy 的结构体 Point

struct Point {
   
   
    x: i32,
    y: i32,
}

fn main() {
   
   
    let p = Point {
   
    x: 0, y: 7 };

    let Point {
   
    x: a, y: b } = p;
    assert_eq!(0, a);
    assert_eq!(