编写使用Result
类型的代码时,您可能需要为用户和开发人员提供不同的行为。
Result
。Err
值时获取堆栈跟踪。如果你发出一个独特的错误,那么搜索它并不困难,但如果错误来自标准库,那么错误可能非常普遍。
例如,如果不手动将每个read
更改为file.read()?
,则无法知道哪个file.read().unwrap()
命令导致意外的文件结尾。
是否有方便的方法从Result
获取堆栈跟踪?
一个弱但可行的解决方案可能是制作一个阅读宏,read_in_release_unwrap_in_debug!(file, data)
......但这感觉非常尴尬。
我有一个文件阅读器,有很多read
个调用,一个失败。我不确定哪个。在运行时,我想将结果推回给调用者。对于调试,我希望失败的读取调用停止或以某种方式让我知道它的行号。
答案 0 :(得分:7)
结果本身没有任何回溯信息,但您可以将其添加到自定义错误类型。
error_chain crate是一个为您生成错误类型的示例,当设置RUST_BACKTRACE
环境变量时,您可以免费获得回溯生成。
您也可以直接使用backtrace库并自行完成。
答案 1 :(得分:1)
如果您使用anyhow
,则可以免费获得!问题是您需要每晚使用并启用一个环境变量:
RUST_BACKTRACE=1 cargo +nightly run
This is the tracking issue for stabilisation和a PR to stabilise it。对于是否需要在稳定之前在no_std中工作还是类似的问题,似乎存在一些分歧。
答案 2 :(得分:0)
我用 easy-error crate 解决了这个要求,而 error-chain crate 也很好。
使用easy-error
中定义的Result作为返回类型,然后使用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(())
}
为了避免一直输入 format!("{}:{}", file!(), line!())
,定义一个宏:
#[macro_export]
macro_rules! code_loc {
() => {
format!("{}:{}", file!(), line!())
};
}
最后的代码将是:
File::open(p).context(code_loc!())?;