Option<T> 是 Rust 里最核心、最重要的枚举类型之一。
如果你已经有中级编程经验(你之前主要用 Python 做数据分析),那么可以把它理解为:
Rust 里“可空值”的安全版本(比
None更安全)
一、什么是 Option?
Option是Rust内置的枚举类型,拥有两个变体,定义如下:
enum Option<T> {
Some(T),
None,
}
它表示:
- ✅
Some(T)—— 有值 - ❌
None—— 没有值
为什么 Rust 不用 null?
Rust 没有 null。
在 Python 中:
x = None
在 Rust 中:
let x: Option<i32> = None;
区别在于:
- Rust 强制你处理 None
- 编译器会检查你是否遗漏情况
- 不可能出现 “空指针异常”
二、基本使用方式
1️⃣ 创建 Option
let a = Some(10);
let b: Option<i32> = None;
2️⃣ match 解构(最基础方式)
let x = Some(5);
match x {
Some(value) => println!("值是 {}", value),
None => println!("没有值"),
}
这是最安全、最完整的处理方式。
三、常用判断方式
1️⃣ is_some / is_none
let x = Some(10);
if x.is_some() {
println!("有值");
}
if x.is_none() {
println!("没值");
}
四、最常用方法(高频 API)
下面是开发中真正高频使用的 API。
1️⃣ unwrap(危险但常用)
let x = Some(5);
println!("{}", x.unwrap());
如果是 None:
let x: Option<i32> = None;
x.unwrap(); // panic!
⚠ unwrap 会在 None 时 panic。
2️⃣ expect(带错误信息)
let x: Option<i32> = None;
x.expect("必须有值");
比 unwrap 好一点,可以打印自定义错误。
3️⃣ unwrap_or(提供默认值)
let x: Option<i32> = None;
let value = x.unwrap_or(100);
println!("{}", value); // 100
4️⃣ unwrap_or_else(惰性计算)
let x: Option<i32> = None;
// 只有在x为None时闭包才会执行
let value = x.unwrap_or_else(|| {
println!("执行默认逻辑");
200
});
区别:
| 方法 | 默认值是否立即计算 |
|---|---|
| unwrap_or | 是 |
| unwrap_or_else | 否(推荐) |
五、函数式操作(最重要部分)
Option 真正强大在于它是函数式可组合的。
1️⃣ map
对 Some 里的值进行转换:
let x = Some(5);
let result = x.map(|v| v * 2);
println!("{:?}", result); // Some(10)
如果是 None:
let x: Option<i32> = None;
x.map(|v| v * 2); // 还是 None
✔ 自动跳过 None
2️⃣ and_then(类似于flatMap)
用于返回 Option 的情况,返回一个新的Option:
let x = Some(5);
let result = x.and_then(|v| {
if v > 3 {
Some(v * 2)
} else {
None
}
});
等价于函数式语言中的 flatMap。
3️⃣ filter
let x = Some(10);
let result = x.filter(|v| *v > 5);
println!("{:?}", result); // Some(10)
let result2 = x.filter(|v| *v > 20);
println!("{:?}", result2); // None
4️⃣ map_or
let x = Some(5);
let result = x.map_or(0, |v| v * 2);
println!("{}", result); // 10
如果 None → 返回默认值
5️⃣ map_or_else(推荐)
let x: Option<i32> = None;
// 惰性计算默认值
let result = x.map_or_else(
|| 0,
|v| v * 2
);
六、? 操作符(最优雅用法)
这是 Rust 最优雅的地方。
示例:链式传播 None
fn add_one(x: Option<i32>) -> Option<i32> {
let value = x?; // 提取Option中的值,如果为None, 直接返回None
Some(value + 1)
}
? 等价于:
match x {
Some(v) => v,
None => return None,
}
✔ 自动传播 None
✔ 极大简化代码
七、Option 在真实开发中的使用场景
1️⃣ HashMap.get
use std::collections::HashMap;
let mut map = HashMap::new();
map.insert("a", 10);
let result = map.get("a"); // Option<&i32>
2️⃣ 字符串查找
let s = "hello";
let pos = s.find("e"); // Option<usize>
3️⃣ 结构体中的可选字段
struct User {
name: String,
age: Option<u8>,
}
八、Option 内存优化(高级)
Rust 有 Null Pointer Optimization(NPO)。
Option<&T>
在内存里和 &T 一样大。因为 None 可以用 0 指针表示。
use std::mem::size_of;
println!("{}", size_of::<Option<&i32>>());
println!("{}", size_of::<&i32>());
两者一样。
✔ 无额外开销
九、Option 和 Result 的区别
| 类型 | 用途 |
|---|---|
| Option | 有/没有 |
| Result | 成功/失败(有错误信息) |
什么时候用 Option?
- 可能不存在
- 不需要错误原因
什么时候用 Result?
- 失败需要说明原因
- IO / 网络 / 解析等操作
十、最佳实践(重要)
❌ 不要滥用 unwrap
生产代码尽量避免:
unwrap()
expect()
✅ 推荐写法
1️⃣ match
match value {
Some(v) => ...
None => ...
}
2️⃣ 使用 ?
let v = option_value?;
3️⃣ 组合式写法
let result = option
.filter(|v| *v > 10)
.map(|v| v * 2)
.unwrap_or(0);
十一、和 Python 对比理解
Python:
if x is not None:
return x + 1
Rust:
fn add(x: Option<i32>) -> Option<i32> {
Some(x? + 1)
}
✔ 更简洁
✔ 编译期安全
十二、总结记忆图
创建:
Some(值)
None
解构:
match
if let
提取:
unwrap()
unwrap_or()
unwrap_or_else()
函数式:
map()
and_then()
filter()
传播:
?