std :: result ::结果恐慌记录

时间:2017-02-25 13:10:39

标签: rust

我在一个单独的线程中运行一些代码:

    fn f1() -> Result<(), String> { Err("err1".to_string()) }
    fn f2() -> Result<(), String> { Err("err2".to_string()) }
    ::std::thread::spawn(move || {
      f1().expect("f1 failed");
      f2().expect("f2 failed");
    });

我也使用log crate进行记录。

结果,我希望panic!拨打error!而不是print!

我找到了panic hook,但在这样的代码中我不喜欢unwrap

panic::set_hook(Box::new(|panic_info| {
    error!("panic occured: {:?}", panic_info.payload().downcast_ref::<&str>().unwrap());
}));

我很担心:

  

这通常是&'static strString

,但并非总是如此

downcast总是不会成功?

1 个答案:

答案 0 :(得分:4)

  

这通常是&'static strString

,但并非总是如此

这意味着开发人员(您使用的库中的一个)可能会使用其他类型。在这种情况下,对downcast_ref的调用将失败。

我的建议是处理您所了解的案例,并添加一个包含默认消息的全包案例。

此外,您还应该考虑打印位置,因为即使没有消息,它也非常有用。

全部告诉:

use std::panic;
use std::ops::Deref;

panic::set_hook(Box::new(|panic_info| {
    let (filename, line) =
        panic_info.location().map(|loc| (loc.file(), loc.line()))
            .unwrap_or(("<unknown>", 0));

    let cause = panic_info.payload().downcast_ref::<String>().map(String::deref);

    let cause = cause.unwrap_or_else(||
        panic_info.payload().downcast_ref::<&str>().map(|s| *s)
            .unwrap_or("<cause unknown>")
    );

    error!("A panic occurred at {}:{}: {}", filename, line, cause);
}));

让我们打开它:

  • 首先我们从该位置获取文件名和行,提供默认值,以防它们未知,
  • 然后我们检查payload是否为String,如果是,则取消引用
  • 然后,如果没有,我们检查它是否是&str,如果没有提供默认值,
  • 最后,我们打印所有累积的信息。