---
title: enum 与模式匹配
url: https://doc.liz6.com/rust/02-type-system/02-enums-and-pattern-matching
locale: zh
area: rust
tags:
- rust
- 类型系统
date: 2026-06-30
modified: 2026-06-30
description: Rust 的 enum 是带标签的联合体(tagged union)——每个 variant 携带独立的数据,编译器保证 match 覆盖所有 variant(穷尽性检查)。Option 和 Result 不是语言内置的,而是标准库用 enum 定义的——这证明了 enum 是 Rust 表达能力最强的类型构造器。
---

# enum 与模式匹配

> Rust 的 enum 是带标签的联合体(tagged union)——每个 variant 携带独立的数据,编译器保证 match 覆盖所有 variant(穷尽性检查)。Option 和 Result 不是语言内置的,而是标准库用 enum 定义的——这证明了 enum 是 Rust 表达能力最强的类型构造器。

## enum 是 tagged union，不只是"枚举"

C 的 enum 只是一组命名整数常量。Rust 的 enum 每个 variant 可以携带不同的数据——它是一个带标签的联合体：

```rust
enum Message {
    Quit,                            // 无数据 — 纯标签
    Move { x: i32, y: i32 },         // 匿名 struct
    Write(String),                   // tuple variant
    ChangeColor(u8, u8, u8),         // 3 个 u8 的 tuple
}
```

编译器为 `Message` 分配的大小足以容纳最大的 variant（`Move` = 两个 i32 = 8 bytes），另加一个 discriminant（tag）字段。对于 `Option<&T>` 这类有 niche 的情况，tag 可以被优化掉。

## Option: Rust 没有 null

Tony Hoare 称 null 是"十亿美元的错误"。Rust 没有 null——可能不存在的值用 `Option<T>` 表示：

```rust
fn safe_div(a: i32, b: i32) -> Option<i32> {
    if b == 0 { None } else { Some(a / b) }
}
// 调用者必须处理 None:
match safe_div(10, 0) {
    Some(result) => println!("{}", result),
    None => println!("division by zero"),
}
```

编译器强制你处理 `None` 的情况——不可能忘记检查。`Option<T>` 是普通类型，不是特殊的 null 标记，所以你可以对 `Option` 使用 map、and_then 等 combinators。

## Result: 错误也是值

异常的问题是它打破了控制流——你无法从函数签名知道它可能抛出什么。`Result<T, E>` 把错误变成返回值的一部分：

```rust
fn parse(s: &str) -> Result<i32, std::num::ParseIntError> {
    s.parse()                        // 返回 Result, 不是 throw
}
```

调用者看到 `Result<i32, ParseIntError>` 就知道——这个函数可能成功返回 `i32`，也可能失败返回解析错误。没有隐藏的控制流。

## Match: 编译期穷尽检查

```rust
match number {
    1 => "one",
    2 => "two",
    // _ => "other",                 // 如果缺少这一行, 编译报错:
                                     // "non-exhaustive patterns"
}
```

编译器会检查 match 是否覆盖了所有可能的 variant。如果类型添加了新 variant（如 enum 加了一个成员），所有 match 这个类型的地方都会编译失败——强迫你显式处理新情况。

## 模式的各种形式

```rust
// 解构
let (x, y, z) = (1, 2, 3);
let Point { x, y } = point;

// ref 模式: 不 move, 借用
let ref r = value;                   // r: &T, value 未被 move

// match guard: 额外条件
match num {
    n if n % 2 == 0 => "even",
    n if n > 10 => "big",
    _ => "other",
}

// @ 绑定: 同时匹配 pattern 和绑定变量
match opt {
    Some(v @ 1..=5) => println!("small: {}", v),
    Some(v) => println!("large: {}", v),
    None => (),
}

// if let / while let: 只关心一个 variant 时的语法糖
if let Some(v) = opt { process(v); }
while let Some(v) = iter.next() { process(v); }
```

## 参考

- **Rust Book**: Chapter 6 (Enums), Chapter 18 (Patterns)
- **Rust Reference**: Match expressions, Patterns

*Keywords: enum, Option, Result, match, pattern, if let, while let, exhaustiveness, tagged union*
