Rust 枚举与模式匹配
enum 表达多形态数据;match / if let 做穷尽处理;Option 等标准枚举是同一思想的实例。
#type / concept
#status / growing
#tech / dev
#resource / rust
[!info] 关联笔记
- 所属 MOC:所有权与类型 · 学习路线
- 前置概念:struct 与方法、流程控制
- 后续概念:Option 与 Result、错误处理
- 容易混淆:trait 对象多态
Rust 枚举与模式匹配
这个概念为什么出现
领域状态常是“多选一且携带不同数据”:
- 支付:支付宝 / 微信 / 银行卡(字段不同)
- 网络:IPv4 / IPv6
- 可空:有值 / 无值
用 struct + 布尔标记容易无效状态;enum 把变体做成类型的一部分,match 强制穷尽处理。
[!abstract] 一句话理解
enum定义一组变体(可承载数据);match按模式解构并穷尽分支,把“忘了处理某种情况”变成编译错误。
最小可运行示例
场景:支付路由——按渠道计算手续费
收银台要根据支付渠道枚举计算手续费;漏渠道应在编译期暴露。
// 业务意图:按支付渠道计算手续费(分)。
// 教学点:枚举变体带数据;match 穷尽;if let 简化单分支。
enum PayChannel {
Card { last4: u16 },
Wallet { provider: String },
Cash,
}
fn fee_cents(ch: &PayChannel, amount: u32) -> u32 {
match ch {
PayChannel::Card { .. } => amount / 100, // 1%
PayChannel::Wallet { provider } if provider == "wechat" => amount / 200,
PayChannel::Wallet { .. } => amount / 150,
PayChannel::Cash => 0,
}
}
fn main() {
let ch = PayChannel::Wallet {
provider: String::from("wechat"),
};
println!("fee={}", fee_cents(&ch, 10_000));
if let PayChannel::Wallet { provider } = &ch {
println!("wallet_provider={provider}");
}
}
建议运行:cargo run
期望输出:
fee=50
wallet_provider=wechat
结合场景再看三个关注点
- 变体可携带不同类型数据
- match 守卫细化钱包分支
- if let 适合只关心一种变体
核心概念与准确模型
- 变体构造:
PayChannel::Cash - 解构:
match/let/ 函数参数模式 _通配;..忽略字段Option/Result就是标准库枚举
impl 也可以给 enum 写方法。
设计动机
- 使非法状态难表示
- 穷尽匹配防漏分支
- 代数数据类型表达力接近函数式语言,同时保留系统性能
边界与误区
- 加
_会吞掉未来新变体,库 API 演进时要权衡 - 大匹配可拆函数
- 不要用数字魔法枚举替代类型化变体
[!warning] 常见误区:用 bool 字段组合模拟 enum 容易出现“is_card && is_cash”无效态;enum 更安全。
工程实践
- 领域状态优先 enum
- 对外 API 匹配时考虑
#[non_exhaustive] - 错误与可空统一用
Result/Option而不是 null
本节总结
- enum = 多形态数据
- match 穷尽
- Option/Result 是同一模式
自测题
- 为什么 match 必须穷尽?
if let相对 match 的代价?
参考答案
- 防止未处理变体在运行时落入默认错误路径。
- 只处理一种模式,其他情况静默忽略,需自觉。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| The Book — Enums and Pattern Matching | 官方书 | 枚举与 match |
| The Book — Patterns | 官方书 | 模式全书 |