开始
rust 中的错误处理并不像其他语言一样使用异常处理错误,rust 将错误分为不可恢复错误和可恢复错误
- 对于可恢复错误,使用
Result<T, E>
类型进行处理 - 对于不可恢复错误,使用 panic 进行处理
不可恢复错误
使用 panic 来处理不可恢复的错误,有两种行为会产生 panic
-
代码执行错误,如越界访问
-
显式调用
panic!
宏1
panic!("Error Message");
产生 panic 后,panic 会打印一个错误信息,之后执行栈展开或终止
- 栈展开:默认行为,rust 会回溯每一个栈帧,清理每个栈帧中的数据,最后退出程序
- 终止:rust 不清理数据,直接退出程序,数据交由操作系统进行清理
打印错误信息时,设置环境变量 RUST_BACKTRACE=1
,可打印出回溯栈
可恢复错误
rust 使用 Result<T, E>
类型来处理可恢复错误,Result
类型是一个枚举
1 | enum Result<T, E> { |
以打开文件为例,打开文件时会返回一个 Result
对象,通过模式匹配进行解构
1 | use std::fs::File; |
若需要判断错误的类型,通常可以调用
error.kind()
获取一个错误类型的枚举,继续进行模式匹配解构
{: .prompt-info}
Err 分支简写
在匹配到 Err
并且显式调用 panic!
宏的情况下,有两个函数可以简化匹配判断
unwrap()
:抛出的 panic 包含默认错误信息expect()
:抛出的 panic 包含自定义错误信息
1 | let file1 = File::open("hello.txt").unwrap(); |
传播错误
当函数需要向外部抛出 Err
时,函数的返回值应该使用 Result<T, E>
类型
以打开文件并读取文件内容为例,打开文件和读取文件都可能发生错误,以函数返回值的形式将错误抛出到外部
1 | use std::fs::File; |
?
运算符
使用 ?
运算符简化抛出错误的分支
1 | use std::fs::File; |
进一步简化为链式调用
1 | use std::fs::File; |
?
运算符被定义为提前返回一个“不合法”的值,使用 ?
运算符需要函数返回值类型与 ?
运算符的性质兼容
最常用的两种可以使用 ?
的类型
Result<T, E>
:提前返回Err
值Option<T>
:提前返回None
值
在 Option<T>
上使用 ?
运算符的例子
1 | // lines()返回一个迭代器,调用next()获取第一个元素,若迭代器中没有元素,则提前返回None |
rust 中提供了一个
Try
trait,对于实现了Try
trait 的类型,都可以使用?
运算符简化