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