Rust 枚举与模式匹配

enum 表达多形态数据;match / if let 做穷尽处理;Option 等标准枚举是同一思想的实例。

#type / concept #status / growing #tech / dev #resource / rust

[!info] 关联笔记

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

结合场景再看三个关注点

  1. 变体可携带不同类型数据
  2. match 守卫细化钱包分支
  3. if let 适合只关心一种变体

核心概念与准确模型

  • 变体构造:PayChannel::Cash
  • 解构:match / let / 函数参数模式
  • _ 通配;.. 忽略字段
  • Option/Result 就是标准库枚举

impl 也可以给 enum 写方法。

设计动机

  • 使非法状态难表示
  • 穷尽匹配防漏分支
  • 代数数据类型表达力接近函数式语言,同时保留系统性能

边界与误区

  • _ 会吞掉未来新变体,库 API 演进时要权衡
  • 大匹配可拆函数
  • 不要用数字魔法枚举替代类型化变体

[!warning] 常见误区:用 bool 字段组合模拟 enum 容易出现“is_card && is_cash”无效态;enum 更安全。

工程实践

  1. 领域状态优先 enum
  2. 对外 API 匹配时考虑 #[non_exhaustive]
  3. 错误与可空统一用 Result/Option 而不是 null

本节总结

  • enum = 多形态数据
  • match 穷尽
  • Option/Result 是同一模式

自测题

  1. 为什么 match 必须穷尽?
  2. if let 相对 match 的代价?
参考答案
  1. 防止未处理变体在运行时落入默认错误路径。
  2. 只处理一种模式,其他情况静默忽略,需自觉。

延伸阅读与资料来源

资料类型支撑内容
The Book — Enums and Pattern Matching官方书枚举与 match
The Book — Patterns官方书模式全书
创建于 2026/7/15 更新于 2026/7/15