第五章:模式匹配 (match) —— 吃了“大力丸”的 switch

Unknown Author 独酌
2025-11-19 Rust, Book

现在我们有了携带不同数据的 Enum,问题来了:我们怎么把数据取出来用呢?

在 JavaScript 里,你可能会写一堆 if (event.type === 'click') 或者 switch 语句。 在 Rust 里,我们有 match

match 是 Rust 中最强大的控制流运算符。它看起来像 switch,但实际上它是一个 "瑞士军"刀级别的解构工具

1. 基本语法

接上章的 Message 枚举例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
enum Message {
Quit,
Write(String),
Move { x: i32, y: i32 }, // 再加一个结构体风格的变体
}

fn process_message(msg: Message) {
match msg {
// 1. 匹配 Quit,没有任何数据
Message::Quit => {
println!("正在退出...");
},

// 2. 匹配 Write,并把里面的 String 解构出来赋值给 text
Message::Write(text) => {
println!("收到消息: {}", text);
},

// 3. 匹配 Move,把 x 和 y 解构出来
Message::Move { x, y } => {
println!("移动到坐标: ({}, {})", x, y);
}
}
}

它的超能力:

  1. 解构 (Destructuring): 注意看 Message::Write(text),我们直接在匹配的同时定义了 text 变量,把枚举里的数据“拿”了出来。

  2. 穷尽性检查 (Exhaustiveness Checking): 这是前端最馋的功能!如果你漏掉了一个 case(比如你忘了处理 Move),Rust 编译时直接报错。它逼着你处理所有可能的情况,杜绝了 “Unhandled case” 导致的 Bug。

2. 通配符 _ (The Placeholder)

有时候枚举有很多种情况,但我们只想处理其中一种,其他的统一忽略。 这时候可以用 _ (下划线),相当于 JS switch 里的 default

1
2
3
4
5
6
7
let number = 7;

match number {
1 => println!("是第一名!"),
// 处理其他所有情况
_ => println!("不是第一名,下次加油"),
}

🧠 随堂小测验

假设你在做一个 红绿灯 系统。

1
2
3
4
5
6
7
8
9
10
11
12
enum TrafficLight {
Red,
Green,
Yellow,
}

fn action(light: TrafficLight) {
match light {
TrafficLight::Red => println!("停!"),
TrafficLight::Green => println!("行!"),
}
}

问题: 如果不写 Yellow 的处理逻辑(把上面代码直接跑),Rust 编译器会怎么做?
A. 编译通过,匹配到 Yellow 时什么都不发生(像 JS 一样)。
B. 编译报错,提示模式未覆盖 (Pattern not covered)。
C. 编译通过,运行时崩溃。

答案:🎯 B. 编译报错。

这就是 Rust 最让人安心的地方。试想一下,几个月后你的同事给 TrafficLight 加了一个 Blue 灯,如果是在 JS 里,你的代码可能还在默默地跑,遇到蓝灯就没有任何反应(产生 Bug)。但 Rust 编译器会立刻按住你:“嘿!这里有个新情况你还没处理呢!”

这让重构代码变得极其安全。

独酌

独酌

小镇码农

相关文章