Rust学习笔记 之 Option

2 阅读3分钟

ChatGPT Image 2026年3月3日 14_13_55.png 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()

传播:
?