Rust Result枚举
外观
Rust Result枚举是Rust标准库中用于错误处理的核心类型之一,它表示一个操作可能成功(包含结果值)或失败(包含错误信息)。与`Option`类型不同,`Result`专门设计用于显式处理错误场景,是Rust“安全优先”理念的重要体现。
基本定义[编辑 | 编辑源代码]
`Result`枚举在标准库中的定义如下:
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Result<T, E> {
Ok(T),
Err(E),
}
其中:
- `T` 表示成功时返回的值的类型
- `E` 表示错误时返回的错误类型
核心特性[编辑 | 编辑源代码]
模式匹配处理[编辑 | 编辑源代码]
最基础的使用方式是通过`match`表达式处理:
fn divide(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err(String::from("Cannot divide by zero"))
} else {
Ok(a / b)
}
}
fn main() {
match divide(10.0, 2.0) {
Ok(result) => println!("Result: {}", result),
Err(e) => println!("Error: {}", e),
}
}
输出:
Result: 5
组合方法[编辑 | 编辑源代码]
`Result`提供了一系列组合方法:
方法 | 描述 | 等效代码 |
---|---|---|
unwrap() |
成功时返回值,失败时panic | match self { Ok(t) => t, Err(e) => panic!() }
|
unwrap_or(default) |
成功时返回值,失败时返回默认值 | match self { Ok(t) => t, Err(_) => default }
|
map(f) |
对成功值应用函数 | match self { Ok(t) => Ok(f(t)), Err(e) => Err(e) }
|
and_then(f) |
链式操作(类似flatMap) | match self { Ok(t) => f(t), Err(e) => Err(e) }
|
错误传播[编辑 | 编辑源代码]
Rust提供了`?`操作符简化错误传播:
use std::fs::File;
fn read_file() -> Result<String, std::io::Error> {
let mut file = File::open("hello.txt")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
等价于:
match File::open("hello.txt") {
Ok(mut file) => {
match file.read_to_string(&mut contents) {
Ok(_) => Ok(contents),
Err(e) => Err(e),
}
}
Err(e) => Err(e),
}
实际应用案例[编辑 | 编辑源代码]
文件处理[编辑 | 编辑源代码]
use std::fs;
use std::io;
fn read_config() -> Result<String, io::Error> {
let config = fs::read_to_string("config.toml")?;
Ok(config)
}
fn main() {
match read_config() {
Ok(config) => println!("Config loaded: {}", config),
Err(e) => println!("Error reading config: {}", e),
}
}
网络请求[编辑 | 编辑源代码]
use reqwest::blocking::get;
fn fetch_data(url: &str) -> Result<String, reqwest::Error> {
let response = get(url)?;
response.text()
}
fn main() {
match fetch_data("https://api.example.com/data") {
Ok(data) => println!("Data received: {}", data),
Err(e) => println!("Request failed: {}", e),
}
}
高级用法[编辑 | 编辑源代码]
自定义错误类型[编辑 | 编辑源代码]
通过实现`std::error::Error` trait创建自定义错误:
#[derive(Debug)]
enum MyError {
Io(std::io::Error),
Parse(std::num::ParseIntError),
}
impl From<std::io::Error> for MyError {
fn from(err: std::io::Error) -> MyError {
MyError::Io(err)
}
}
fn process_file() -> Result<i32, MyError> {
let contents = std::fs::read_to_string("data.txt")?;
let num = contents.trim().parse::<i32>()?;
Ok(num * 2)
}
错误转换[编辑 | 编辑源代码]
使用`map_err`进行错误类型转换:
fn string_length(s: &str) -> Result<usize, String> {
s.parse::<i32>()
.map(|n| n as usize)
.map_err(|e| format!("Parse failed: {}", e))
}
可视化流程[编辑 | 编辑源代码]
数学表示[编辑 | 编辑源代码]
Result类型可以形式化表示为: 其中:
- 表示成功情况
- 表示错误情况
最佳实践[编辑 | 编辑源代码]
1. 优先使用`?`操作符而非`unwrap()` 2. 为库代码定义具体的错误类型 3. 使用`thiserror`或`anyhow`等库简化错误处理 4. 在应用程序入口处统一处理错误 5. 为错误实现`std::error::Error` trait
参见[编辑 | 编辑源代码]
- Rust Option枚举
- Rust错误处理机制
- Rust trait系统