2017-02-25 27 views
1

我在一个单独的线程中运行一些代码:的std ::结果::结果恐慌登录

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总是成功吗?

回答

3

这将常见的,但并非总是如此,是&'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); 
})); 

让我们来解开它:

  • 首先,我们取该定位的文件名和行提供的情况下,默认他们是未知的,
  • 然后我们检查是否​​是String,如果是这样解除引用,
  • 那么,如果没有,我们检查它是否是&str,如果不提供默认设置,最后打印所有累计信息。