Skip to content

模式匹配

模式和匹配是两个不同的概念。

在 Rust 中,模式匹配最常用的就是 match(要求穷尽所有可能性) 和 if let(满足单一可能性)。

作用是

  • 减少分支代码造成的嵌套循环
  • 方便解构复杂类型

模式的组成

  • 字面值(Literals):例如数字或字符串
  • 解构数据结构:数组、枚举、结构体、元组等
  • 变量 (Variables):命名的变量
  • 通配符 (Wildcards):_表示任意值
  • 占位符(Placeholders):尚未具体定义的部分

使用位置

  • 比较模式和值,匹配成功则提取并使用数据
  • 一般作为match表达式的内部分支。

以下是模式使用的位置:

  1. match 表达式

    • 必须穷尽所有可能性

    • 分支使用 PATTERN => EXPRESSION 形式

    • 示例:

      rust
      match x {
          Some(i) => Some(i + 1),
          None => None,
      }
  2. if let 表达式

    • 用于只关心一种匹配情况的简写

    • 可搭配 else ifelse if let 使用

    • 示例:

      rust
      if let Some(color) = favorite_color {
          println!("Using {color} as background");
      } else if is_tuesday {
          println!("Tuesday is green day!");
      }
  3. while let 条件循环

    • 只要模式匹配就一直循环

    • 示例:

      rust
      while let Ok(msg) = rx.recv() {
          println!("Got: {}", msg);
      }
  4. for 循环

    • 循环变量本身就是模式

    • 可用于解构:

      rust
      for (index, value) in v.iter().enumerate() {
          println!("{} is at index {}", value, index);
      }
  5. let 语句

    • 所有 let 绑定都是模式匹配

    • 示例:

      rust
      let (x, y, z) = (1, 2, 3); // 解构元组
  6. 函数参数

    • 参数也是模式

    • 示例:

      rust
      fn print_coordinates(&(x, y): &(i32, i32)) {
          println!("Current location: ({}, {})", x, y);
      }

语法

  1. 匹配字面值

    rust
    let x = 1;
    match x {
        1 => println!("one"),
        2 => println!("two"),
        _ => println!("other"),
    }
  2. 匹配命名变量

    • 注意变量遮蔽问题

    • 示例:

      rust
      match Some(5) {
          Some(y) => println!("Matched, y = {}", y), // 新建变量 y
          _ => (),
      }
  3. 多模式匹配

    • 使用 | 表示"或"
    rust
    match x {
        1 | 2 => println!("one or two"),
        _ => println!("other"),
    }
  4. 范围匹配

    • 使用 ..= 匹配闭区间
    rust
    match x {
        1..=5 => println!("one through five"),
        _ => println!("other"),
    }
  5. 解构

    • 结构体:

      rust
      let p = Point { x: 0, y: 7 };
      let Point { x, y } = p;
    • 枚举:

      rust
      match msg {
          Message::Quit => println!("Quit"),
          Message::Move { x, y } => println!("Move to {}, {}", x, y),
      }
    • 嵌套结构:

      rust
      match msg {
          Message::ChangeColor(Color::Rgb(r, g, b)) => println!("RGB"),
          _ => (),
      }
  6. 忽略值

    • 使用 _ 忽略整个值
    • 使用 _var 忽略未使用变量(避免警告)
    • 使用 .. 忽略剩余部分
    rust
    let (x, ..) = (1, 2, 3); // 只绑定x,忽略其余
  7. 匹配守卫

    • 额外的 if 条件
    rust
    match num {
        Some(x) if x % 2 == 0 => println!("Even"),
        Some(x) => println!("Odd"),
        None => (),
    }
  8. @ 绑定

    • 绑定值到变量同时测试
    rust
    match msg {
        Message::Hello { id: id_variable @ 3..=7 } => {
            println!("Found id in range: {}", id_variable)
        }
        _ => (),
    }

可反驳性(Refutability)

  1. 不可反驳模式(Irrefutable)

    • 总能匹配成功的模式
    • 用于:let 语句、函数参数、for 循环
    • 示例:let x = 5;
  2. 可反驳模式(Refutable)

    • 可能匹配失败的模式
    • 用于:match 分支(除最后一个)、if letwhile let
    • 示例:if let Some(x) = value
  3. 错误处理

    • 在需要不可反驳模式的地方使用可反驳模式会报错
    • 修复方法:改用 if let 等接受可反驳模式的语法