欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 幼教 > 深入浅出 Rust 的强大 match 表达式

深入浅出 Rust 的强大 match 表达式

2025/2/22 2:25:24 来源:https://blog.csdn.net/weixin_43114209/article/details/145339367  浏览:    关键词:深入浅出 Rust 的强大 match 表达式

一、什么是 match

match 表达式能让你将一个值与一系列“模式”进行比较,并根据匹配到的模式执行相应的代码。常见的模式类型包括:

  • 字面量(例如 37"hello"
  • 枚举(Enum)变体(例如 Coin::Penny
  • 变量绑定(如在 Coin::Quarter(state) 中捕获 state
  • 通配符(_),用来匹配任何值
  • 其他更高级的模式(在 Rust 程序设计语言 第 19 章会有深入讲解)

从结构上看,可将 match 类比为一个“分类器”或“检索器”:

  1. 传入的值依次与每个模式进行匹配。
  2. 一旦找到匹配的模式,运行对应的代码,并返回结果。
  3. 如果没有匹配到,继续检查下一个模式。
  4. match 必须覆盖所有可能的值,也就是“穷尽匹配”。

二、示例:硬币分类

先来一个经典示例。假设我们有一个表示美国硬币的枚举 Coin

#[derive(Debug)]
enum UsState {Alaska,// ... 其他州
}enum Coin {Penny,Nickel,Dime,Quarter(UsState),
}

如果要写一个函数 value_in_cents,返回某个硬币的美分值,就可以这样:

fn value_in_cents(coin: Coin) -> u8 {match coin {Coin::Penny => 1,Coin::Nickel => 5,Coin::Dime => 10,Coin::Quarter(state) => {println!("来自 {:?} 州的 25 美分硬币!", state);25}}
}

2.1 解析

  1. match coin:这里的 coin 就是要进行“模式匹配”的值。
  2. 匹配分支(arms):每一行(如 Coin::Penny => 1)被称为一个“匹配分支”或“分支模式”。
  3. 模式与代码Coin::Penny => 1 表示如果 coin 的值是 Coin::Penny,就返回 1。对于 Coin::Quarter(state),还会打印出所在州,并返回 25

Rust 会逐个检查 coin 与各个分支是否匹配,一旦匹配到就执行对应的代码并返回该结果。因为我们覆盖了 PennyNickelDimeQuarter 四种变体,所以 Rust 确定所有情况都被“穷尽”,编译通过。

三、绑定内部值

Coin::Quarter(state) 这个分支里,我们不仅仅匹配到 Quarter,还把这个硬币的具体“州”数据绑定到了变量 state 上,然后就能在分支中使用它,比如打印或做进一步处理。这种模式绑定(pattern binding)让我们可以优雅地解构枚举内部的数据。

四、与 Option<T> 搭配使用

在实际开发中,match 常被用来搭配 Option<T> 处理“有值”或“无值”的情形。示例:我们要写一个函数 plus_one,它接受 Option<i32>,如果里面有值就加一,如果没有值就原样返回 None

fn plus_one(x: Option<i32>) -> Option<i32> {match x {None => None,Some(i) => Some(i + 1),}
}

4.1 工作原理

  • 当传入 None 时,与分支 None => None 匹配,直接返回 None
  • 当传入 Some(i) 时,与分支 Some(i) => Some(i + 1) 匹配,此时 i 会绑定到内部的数字,然后执行 i + 1,最后返回新的 Some(i + 1)

借助枚举的严格穷尽性,Rust 强制要求我们显式处理 None,从而避免了“null 引用”带来的潜在错误。

五、穷尽匹配:覆盖所有可能分支

Rust 对 match 的“穷尽匹配”有严格要求:你必须确保所有可能情况都能被匹配到,否则编译器会报错提示遗漏了哪些情况。比如,我们如果在 plus_one 中遗漏了 None

fn plus_one_bug(x: Option<i32>) -> Option<i32> {match x {Some(i) => Some(i + 1),}
}

编译器就会报错,提醒你还没有处理 None。这项特性让我们在编译期就能暴露逻辑漏洞,大幅降低 bug 产生的概率。

六、通配模式 _

在有些场景下,我们只想对少数情况做特殊处理,所有其他情况统一处理。Rust 提供了 _ 来做“通配”匹配(也称“捕获所有剩余情况”)。例如:

fn dice_roll_outcome(roll: u8) {match roll {3 => fancy_hat(),7 => remove_hat(),_ => reroll(), // 其余的全部执行 reroll()}
}fn fancy_hat() { /* ... */ }
fn remove_hat() { /* ... */ }
fn reroll() { /* ... */ }

这里 _ 可以匹配任何值,但不会将其绑定到变量中。如果你确实需要使用那个值,可以把 _ 换成一个命名变量(例如 other),这样就能在分支里使用了。

七、分支中的多行代码

大多数时候,每个匹配分支只返回一个简单值,不需要花括号。如果需要在分支中执行多行操作,可以使用花括号包起来,最后一行将作为返回值。例如:

fn value_in_cents(coin: Coin) -> u8 {match coin {Coin::Penny => {println!("幸运的便士!");1},Coin::Nickel => 5,Coin::Dime => 10,Coin::Quarter(state) => {println!("来自 {:?} 州的 25 美分硬币!", state);25},}
}

这里当匹配到 Coin::Penny 时,会先打印 “幸运的便士!”,然后返回 1

八、总结与收获

  1. 强大的模式匹配
    Rust 的模式匹配远不止简单的“值相等”。后续还可以学习更高级的模式,如解构结构体、元组、范围匹配、匹配守卫(guard)等。

  2. 穷尽性
    match 要求你必须处理所有可能情况,这在很大程度上减少了遗漏错误。

  3. Enum + match = 强力组合
    Enum 天生与 match 搭配;在模式中既能指定变体,又能访问内部数据。

  4. 通配模式 _
    _ 用于捕获其他未匹配的情况,避免写过多重复分支;若要使用未匹配的值,则使用命名变量替代 _

  5. 匹配分支的返回值
    匹配分支中的代码是一个表达式,match 的最终结果就是匹配分支所产生的值。

九、结语

Rust 的 match 表达式是编写安全、易读且可靠的代码的有力工具。它不仅迫使你在编译阶段考虑到所有可能的情况,而且还能让你专注于“要对每种情况如何处理”这一核心逻辑。很多 Rust 开发者在接触到这种枚举加模式匹配的风格后,纷纷表示“再也离不开了”。

如果你想进一步了解更多高级模式的细节(比如范围匹配、复杂数据结构的解构匹配等),可以阅读 The Rust Programming Language 第 19 章。相信随着对 match 越来越熟悉,你会发现它能让 Rust 代码既优雅又高效!

祝你匹配愉快,写出更多健壮且清晰的 Rust 代码!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词