楼层: 首页/ 软件技术/ Rust 语言基础/ 枚举 Enum 与模式匹配:Option 和 Result
06

枚举 Enum 与模式匹配:Option 和 Result

Enum · Pattern Matching · Option · Result

Rust 的枚举比 Java 的 enum 强大得多——每个变体可以带着不同类型的数据。配合 match,它能同时替代 Java 的 sealed class、null 和 checked exception。

定义枚举:变体能带数据

enum Message { Quit, // 无数据 Move { x: i32, y: i32 }, // 具名字段 Write(String), // 包一个 String ChangeColor(i32, i32, i32), // 包三个整数 } fn process(msg: Message) { match msg { Message::Quit => println!("退出"), Message::Move { x, y } => println!("移动到 ({}, {})", x, y), Message::Write(text) => println!("文本:{}", text), Message::ChangeColor(r, g, b) => println!("颜色 rgb({},{},{})", r, g, b), } } fn main() { process(Message::Write(String::from("你好"))); process(Message::Move { x: 10, y: 20 }); }
$ cargo run 文本:你好 移动到 (10, 20)

Option<T>:Rust 没有 null

论用类型逼你处理"可能为空"

Java 的 NPE 噩梦,根源是引用随便可以是 null。Rust 根本没有 null——值"可能不存在"这件事,用枚举 Option<T> 表示:要么 Some(v)(有值),要么 None(没值)。你想拿到里面的 T,编译器逼你先处理 None 的情况,不处理就编不过。空指针异常从根上消失。

fn main() { let name: Option<&str> = Some("Tom"); let nothing: Option<i32> = None; // 常用方法:map / unwrap_or / is_some let upper = name.map(|n| n.to_uppercase()); // 有值就加工,没值还是 None let fallback = nothing.unwrap_or(-1); // 是 None 就给默认值 // match 显式处理两种情况 match name { Some(v) => println!("名字是 {}", v), None => println!("没名字"), } println!("{:?} {}", upper, fallback); }
$ cargo run 名字是 Tom Some("TOM") -1

Result<T, E>:可能失败的函数

论错误不是抛出来,是返回出来

Rust 没有 checked exception,函数可能失败就返回 Result<T, E>:成功是 Ok(T),失败是 Err(E)。调用者必须处理。这跟 Java 的受检异常思路类似,但用类型系统表达,更干净。

fn divide(a: f64, b: f64) -> Result<f64, String> { if b == 0.0 { Err(String::from("除数不能为零")) } else { Ok(a / b) } } fn main() { match divide(10.0, 2.0) { Ok(v) => println!("结果 {}", v), Err(e) => println!("出错:{}", e), } // unwrap:有值就给值,是 Err 就 panic(只在示例/测试里用) let v = divide(9.0, 3.0).unwrap(); println!("{}", v); }
$ cargo run 结果 5 3

match 模式匹配的花式用法

fn main() { let p = (0, 7); match p { (0, 0) => println!("原点"), (0, y) => println!("在纵轴 y={}", y), (x, 0) => println!("在横轴 x={}", x), (x, y) if x == y => println!("在对角线"), // 守卫 if _ => println!("其他点"), } // matches! 宏:判断一个值是否匹配某个模式,返回 bool let ok = matches!(Some(3), Some(_) | None); println!("{}", ok); }
$ cargo run 在纵轴 y=7 true