Rust中的模式匹配

模式匹配(Pattern Matching) 是一种强大的控制流工具,主要用于解构数据结构、匹配值和控制程序分支。常见匹配结构有:

  • match 表达式
  • if let
  • while let
  • for 循环
  • 函数参数解构

match

match是模式匹配的核心:

  • 穷尽性检查:编译器强制要求处理所有可能情况。
  • 模式顺序:按从上到下的顺序匹配,首个匹配成功即执行对应分支。
    • _ 匹配任何值,用于忽略不需要的值;
    • .. 忽略结构体 / 元组的部分字段;
    • |(管道符)实现或逻辑匹配,同时匹配多个;
    • ..=范围匹配,匹配指定范围内值;
    • @绑定,将匹配值绑定到变量;
  • 返回值:每个分支的表达式结果必须是相同类型。
  • =>分割模式与执行代码。

字面量模式

直接匹配具体的值(字面量),支持数字、字符串、布尔值等。

rust 复制代码
let x = 3;
match x {
    1 => println!("One"),
    z @ (2 | 3) => println!("or-{}", z),   // 多重匹配
    z @ 4..=6 => println!("rang-{}", z), 	// 范围匹配
    _ => println!("Other"),	// 默认匹配
}

守卫模式

在模式后添加 if 条件,进一步过滤匹配(仅当模式匹配且条件为真时生效)。

rust 复制代码
let num = 8;

match num {
    n if n % 2 == 0 => println!("Even: {}", n), // 8是偶数,匹配成功
    n => println!("Odd: {}", n),
}

let pair = (2, 3);
match pair {
    (x, y) if x + y == 5 => println!("Sum is 5"), // 2+3=5,匹配成功
    _ => println!("Sum is not 5"),
}

引用模式

模式匹配时,默认会移动(Move)数据的所有权;通过ref进行引用而非移动。通常会自动推断引用的匹配(match ergonomics),但在复杂的解构中需要显式写 refref mut依然很有用:

所有权与引用

rust 复制代码
// 引用类型
let rOne = Some(String::from("hello"));
match rOne {
    Some(ref x) => println!("x = {}", x), 
    _ => {}
}
println!("rOne: {:?}", rOne);

// 所有权移动
let rTwo = Some(String::from("hello"));
match rTwo {
    Some(x) => println!("x = {}", x), 
    _ => {}
}
// 此时rTwo已没有所有权,不能再打印
// println!("rTwo: {:?}", rTwo);

// 对原值进行修改(引用)
let mut a = Some(1);
match a {
    Some(ref mut v) => *v += 10,
    None => (),
}

println!("a = {:?}", a); // 输出 Some(11)

绑定

可以在匹配时绑定部分匹配值:

rust 复制代码
enum Message { Hello { id: i32 } }

let msg = Message::Hello { id: 7 };

match msg {
    Message::Hello { id: id_variable @ 3..=10 } => {
        println!("id 在范围内: {}", id_variable);
    }
    Message::Hello { id } => {
        println!("id 不在范围: {}", id);
    }
}

复合结构匹配

结构体模式

可自动解构结构中的字段,

rust 复制代码
struct Point { x: i32, y: i32 }

let p = Point { x: 10, y: 20 };
match p {
    Point { x: 0, y } => println!("On y-axis at {}", y),
    Point { x, y: 0 } => println!("On x-axis at {}", x),
    Point { x, y } => println!("({}, {})", x, y),
    // Point { x, .. } => println!("({}, -)", x), //不关心y
}

枚举模式

枚举是模式匹配的核心应用场景,用于匹配不同的枚举变体(Variant)。

rust 复制代码
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

let msg = Message::Move { x: 5, y: 10 };
match msg {
    Message::Quit => println!("Quit"),
    // 解构结构体变体的字段
    Message::Move { x, y } => println!("Move to ({}, {})", x, y), // 匹配成功
    // 解构单值变体
    Message::Write(s) => println!("Write: {}", s),
    // 解构元组变体
    Message::ChangeColor(r, g, b) => println!("Color: ({}, {}, {})", r, g, b),
}

切片模式

匹配切片或数组的结构(长度固定时可精确匹配,长度不固定时用 .. 匹配任意长度)。

rust 复制代码
let arr = [1, 2, 3, 4];

// 匹配长度为4的数组,且首元素为1,末元素为4
match arr {
    [1, a, b, 4] => println!("a={}, b={}", a, b), // a=2, b=3
    _ => println!("Other"),
}

let slice = &[10, 20, 30];

// 匹配切片的开头和结尾,中间用 .. 匹配任意长度
match slice {
    [first, .., last] => println!("First: {}, Last: {}", first, last), // First:10, Last:30
    [] => println!("Empty slice"),
}

其他模式匹配

if let

当只需要处理一种匹配情况,其他情况忽略时使用

rust 复制代码
let option = Some(5);

// 等价于 match option { Some(x) => ..., _ => () }
if let Some(x) = option {
    println!("Got: {}", x); // 输出 "Got: 5"
}

while let

当需要反复匹配某个模式,直到不匹配时退出循环。

rust 复制代码
let mut stack = vec![1, 2, 3];

// 每次弹出最后一个元素,直到栈为空
while let Some(top) = stack.pop() {
    println!("Popped: {}", top); // 依次输出 3、2、1
}

for循环

在循环中解构迭代器的元素

rust 复制代码
let pairs = vec![(1, "one"), (2, "two")];

// 解构元组 (数字, 字符串)
for (num, s) in pairs {
    println!("{}: {}", num, s); // 输出 "1: one"、"2: two"
}
相关推荐
doiito1 小时前
【Agent Harness】Gliding Horse 核心设计理念,不跟风开发自己的AI Agent
ai·rust·架构设计·系统设计·ai agent
花褪残红青杏小11 小时前
Rust图像处理第6节- 均值模糊 & 中值模糊:3×3 邻域的两种经典玩法
rust·webassembly·图形学
子兮曰15 小时前
前端工具链的「Rust 化」:一场没有赢家的军备竞赛?
前端·后端·rust
星栈17 小时前
写 Dioxus Demo 不难,难的是把它写成项目
前端·rust·前端框架
mCell19 小时前
【锐评】桌面端技术营销:别拿跑分当工程判断
前端·rust·electron
武子康1 天前
调查研究-201 Rust 里的 dev build 和 release build:为什么同一份代码性能差这么多?
后端·架构·rust
doiito1 天前
【Agent Harness】Gliding Horse 的 L2 作战地图:让多 Agent 协作从“摸黑”变成“透明”
ai·rust·架构设计·系统设计·ai agent
星栈2 天前
我用 Rust + Dioxus 做了个全栈跨平台笔记应用:再把新建、编辑和交付补上
前端·rust·前端框架
独孤留白2 天前
从C到Rust:基本类型 C 的隐式不确定 vs Rust 的显式确定
rust
清晨很温柔啊2 天前
# 用 Rust 手搓 AI 自演化主板:当 18 个异构器官长出 C++ 骨骼
rust