Rust 中 ResultOption 的区别


1. 核心用途

类型用途
Result<T, E>表示操作可能成功Ok(T))或失败Err(E)),需处理错误原因。例如文件操作、网络请求等可能失败且需要错误信息的场景。
Option<T>表示值可能存在Some(T))或不存在None)。适用于无需错误信息的场景,如查找元素、可选配置等。

示例

// Result:文件读取(可能成功或失败)
let file = File::open("hello.txt"); // Result<File, std::io::Error>
 
// Option:从集合中查找元素
let vec = vec![1, 2, 3];
let value = vec.get(5); // Option<&i32>(此处为 None)

2. 错误信息

类型错误处理
Result<T, E>失败时通过 Err(E) 携带具体错误信息(如 std::io::Error),便于调试和处理。
Option<T>仅表示值缺失(None),不提供错误细节

示例

// Result 的错误信息传递
fn read_file() -> Result<String, std::io::Error> {
    let content = std::fs::read_to_string("missing.txt")?; // 错误时返回 Err
    Ok(content)
}
 
// Option 的 None 无额外信息
fn find_even(numbers: &[i32]) -> Option<&i32> {
    numbers.iter().find(|&&x| x % 2 == 0)
}

3. 泛型参数

类型泛型参数
Result<T, E>两个参数:T(成功类型),E(错误类型)。
Option<T>一个参数:T(值的类型)。

自定义 Result 别名示例

type MyResult = Result<u32, String>; // 成功返回 u32,失败返回 String
fn div(x: u32, y: u32) -> MyResult {
    if y == 0 { Err("Division by zero".to_string()) }
    else { Ok(x / y) }
}

4. 处理方式

两者均需通过 match? 操作符处理所有可能情况,确保代码健壮性。

match 处理示例

// 处理 Result
match File::open("file.txt") {
    Ok(file) => println!("File opened: {:?}", file),
    Err(e) => println!("Error: {:?}", e),
}
 
// 处理 Option
match vec.get(2) {
    Some(val) => println!("Value: {}", val),
    None => println!("Index out of bounds"),
}

? 操作符的差异

  • Result? 遇到 Err(e) 会提前返回错误。
  • Option? 遇到 None 会提前返回 None

5. 转换方法

Option<T>相当于Result<T, ()>

image-20250322113003733

操作示例
OptionResult使用 ok_orok_or_else 添加错误信息:
let res: Result<i32, &str> = Some(5).ok_or("Value missing");
ResultOption使用 ok() 丢弃错误,或 err() 获取错误:
let opt = res.ok();

6. 适用场景总结

场景推荐类型
需要处理错误原因(如I/O、网络)Result<T, E>
仅需表示值是否存在(如查找元素)Option<T>
需传播错误(链式调用)Result + ?
可选参数或配置项Option<T>

关键对比表

特性Result<T, E>Option<T>
含义成功或失败(含错误)值存在或不存在
变体Ok(T), Err(E)Some(T), None
错误信息通过 E 类型传递
泛型参数2个(TE1个(T
适用操作高风险操作(可能失败)低风险操作(简单值缺失)

image-20250322112433398

参考资料