ide*_*n42 7 error-handling rust
编写使用Result类型的代码时,您可能需要为用户和开发人员提供不同的行为.
Result.Err在创建值时获取堆栈跟踪.如果您发出唯一错误,则搜索它并不困难,但如果错误来自标准库,则错误可能非常通用.
例如,它是不可能知道哪个read命令造成的意外结束的文件,而不手动更改每file.read()?到file.read().unwrap().
有没有一种方便的方法来获取堆栈跟踪Result?
一个弱但可行的解决方案可能是制作阅读宏,read_in_release_unwrap_in_debug!(file, data)......但这感觉非常尴尬.
我有一个文件阅读器有很多read电话,一个失败.我不确定哪个.在运行时,我想将结果推回给调用者.对于调试,我希望失败的读取调用停止或以某种方式让我知道它的行号.
结果本身没有任何回溯信息,但您可以将其添加到自定义错误类型.
该error_chain箱子是为您生成一个错误类型,其中,当你回溯代免费的例子RUST_BACKTRACE环境变量设置.
您也可以直接使用backtrace库并自己完成.
如果你使用,anyhow你可以免费得到这个!问题是您需要每晚使用并启用环境变量:
RUST_BACKTRACE=1 cargo +nightly run
Run Code Online (Sandbox Code Playgroud)
这是稳定的跟踪问题,以及稳定它的 PR。看起来在稳定之前是否需要在 no_std 中工作或类似的事情存在一些分歧。
我用easy-error crate 解决了这个要求,而error-chain crate 也很好。
使用中定义的Resulteasy-error作为返回类型,然后使用context方法转换其他Result类型。
最重要的是将信息传递给context带有行号的方法。
use easy_error::{Result, ResultExt};
use std::path::PathBuf;
fn test_open() -> Result<()> {
let mut p = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
p.push("resources/test/songs.json");
File::open(p).context(format!("{}:{}", file!(), line!()))?;
Ok(())
}
Run Code Online (Sandbox Code Playgroud)
format!("{}:{}", file!(), line!())为了避免一直打字,定义一个宏:
#[macro_export]
macro_rules! code_loc {
() => {
format!("{}:{}", file!(), line!())
};
}
Run Code Online (Sandbox Code Playgroud)
最后代码将是:
File::open(p).context(code_loc!())?;
Run Code Online (Sandbox Code Playgroud)