Rust中模式匹配

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

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

match

match是模式匹配的核心:

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

字面量模式

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

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"),
}

引用模式

当模式中的值是引用类型时,需要注意 ref 和 ref mut(否则会产生移动语义,原有变量的所有权会丢失):

rust 复制代码
let tmp = &Some(10); // 临时值的引用

match tmp {
    // Some(x) => println!("x = {}", x),  	// x为&i32
    &Some(x) => println!("x = {}", x),		// x为i32
    _ => {}
}

所有权与引用

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!("rOne: {:?}", rTwo);

可修改引用,对原值进行修改

rust 复制代码
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"
}
相关推荐
离歌漠6 小时前
《我用 Tauri 做了一个本地开发工具箱》
rust·typescript·vue
小小龙学IT11 小时前
Python Polars 高性能数据处理引擎深度解析
开发语言·python·rust·1024程序员节
zzu123zsw13 小时前
为什么 Python 做 Agent 总在并发中崩溃?拆解 Blockcell 在 Rust 下的 Host-Cell 隔离与自愈状态机
开发语言·python·rust·大模型·ai agent
hsg7714 小时前
简述:基于Ubuntu24编译发布rust开发的html+web后端服务的方法
rust·1024程序员节
zzu123zsw15 小时前
当 GPU 加速渲染遇上无头组件:拆解 Yororen UI 在 GPUI 生态下的状态解耦与 XML 模板实践
xml·ui·rust·gui·gpui
传奇开心果编程1 天前
【Rust入门练中学】第6课:结构体与方法
开发语言·rust·结构体·编程语言理论·结构体方法·编程通用语言
本地化文档1 天前
cutile-rs-book-l10n
rust·gpu·nvidia·cuda·sphinx·crowdin
qq_406981031 天前
大白话rust系列09 函数调用两次有什么错?
开发语言·python·rust
康小旺1 天前
TypeScript 编译器开始卷 Rust 了:Cloudflare 的 tsrs 到底想干嘛?
rust·typescript
Norna1 天前
时间轮的 +1,为什么最后只留在顶层
rust