错误处理是Rust编程中极其重要的一部分,Rust提供了多种机制来处理可能出现的错误情况,确保程序的健壮性和安全性。
1. Rust错误处理哲学
Rust将错误分为两大类:
- 可恢复错误(Recoverable):使用
Result<T, E>
类型表示 - 不可恢复错误(Unrecoverable):使用
panic!
宏处理
// 不可恢复错误示例
fn main() {
panic!("这是一个不可恢复错误,程序将终止");
}
2. Result 类型基础
Result
是Rust中处理可恢复错误的主要方式:
enum Result<T, E> {
Ok(T), // 操作成功,包含结果值
Err(E), // 操作失败,包含错误信息
}
2.1 基本用法
use std::fs::File;
fn main() {
// 尝试打开文件
let file_result = File::open("hello.txt");
match file_result {
Ok(file) => {
println!("文件打开成功: {:?}", file);
},
Err(error) => {
println!("文件打开失败: {}", error);
}
}
}
2.2 错误传播
Rust鼓励使用 ?
操作符来传播错误:
use std::fs::File;
use std::io::{self, Read};
fn read_username_from_file() -> Result<String, io::Error> {
let mut username = String::new();
// ? 操作符会自动处理错误传播
File::open("hello.txt")?.read_to_string(&mut username)?;
Ok(username)
}
3. 自定义错误类型
3.1 简单错误类型
#[derive(Debug)]
enum MyError {
IoError(std::io::Error),
ParseError(std::num::ParseIntError),
CustomError(String),
}
impl From<std::io::Error> for MyError {
fn from(error: std::io::Error) -> Self {
MyError::IoError(error)
}
}
impl From<std::num::ParseIntError> for MyError {
fn from(error: std::num::ParseIntError) -> Self {
MyError::ParseError(error)
}
}
3.2 使用 thiserror 宏
更推荐使用 thiserror
库来简化错误定义:
use thiserror::Error;
#[derive(Error, Debug)]
enum MyError {
#[error("I/O错误: {0}")]
Io(#[from] std::io::Error),
#[error("解析错误: {0}")]
Parse(#[from] std::num::ParseIntError),
#[error("自定义错误: {0}")]
Custom(String),
#[error("未知错误")]
Unknown,
}
4. 错误处理实用模式
4.1 unwrap 和 expect
// unwrap