Rust高效错误处理方案:anyhow
总结摘要
本文介绍了 Rust 中的 anyhow 库,用于高效且灵活的错误处理。anyhow 提供了 anyhow::Error 类型,支持上下文附加、错误类型检查、错误回溯等功能。通过 Result<T, anyhow::Error> 或 anyhow::Result<T> 替换函数返回值,可以简化错误传播。context 和 with_context 宏用于添加上下文信息,帮助开发者快速定位问题。downcast 方法可用于检查具体错误类型。此外,anyhow 还支持在 no-std 模式下使用,并兼容自定义错误类型。
anyhow库提供了一个 anyhow::Error
类型,基于 std::error::Error
trait上面做的扩展,可以很方便的用于进行 Rust 程序的错误处理。
快速使用
如果需要在项目中添加 anyhow
依赖,可以使用如下命令:
|
|
也可以直接编辑 Cargo.toml
文件,并添加一下内容:
注意:需要使用 rustc 1.39+版本
用法
- 使用
Result<T, anyhow::Error>
或者等效的anyhow::Result<T>
,来替换任何返回Result<T, E>
类型的函数返回值。
- 附加context上下文可以有效的帮助开发人员排查问题到底出在哪里。如果没有更多的上下文信息,返回像“No such file or directory”这样的低级错误信息就很烦人,因为看不出来具体到底是哪个文件或者目录不存在。
- 支持使用
downcast
检查具体的错误类型,也可以做类型替换。
如果使用Rust版本 ≥ 1.65,如果底层错误类型没有提供自己的错误类型,则会捕获并打印一个错误backtrace。为了查看backtrace信息,必须通过
std::backtrace
中描述的环境变量来启用backtrace:- 如果你想让panic和error都有backtrace,设置
RUST_BACKTRACE=1
- 如果你只想让 error 有 backtrace,设置
RUST_LIB_BACKTRACE=1
- 如果你只想让 panic 有 backtrace,设置
RUST_BACKTRACE=1
和RUST_LIB_BACKTRACE=0
- 如果你想让panic和error都有backtrace,设置
anyhow适用于任何实现了
std::error::Error
trait的错误类型,包括你在自己的 crate 中定义的错误类型。我们不绑定derive(Error)
宏,但是你可以使用 thiserror 库来快速定义错误。
- 可以使用
anyhow!
宏来构建一次性的错误信息,该宏支持通过字符串和一些变量插值来定义anyhow::Error
。
|
|
等效的也可以使用bail!
宏:
|
|
No-std支持
在 no_std 模式下,几乎所有相同的 API 都可用并且以相同的方式工作。 如果要在 no_std 模式下添加依赖 anyhow,请在 Cargo.toml
中禁用我们默认启用的std
功能。 需要一个全局allocator。
由于基于?
的错误转换依赖于 std 下面的std::error::Error
trait,所以如果在 no-std 模式下,处理非 anyhow 错误类型时,需要显式的使用.map_err(Error::msg)
来返回一个 anyhow 的错误类型。