繁体   English   中英

Rust:如何覆盖默认的报错方式?

[英]Rust: how to override the default way of reporting error?

当 Rust 发生错误时,大多数 Rust 标准和 3rd 方库(例如无论如何)都会简单地将错误消息打印到 stdout/stderr。 我需要的是用我自己的函数覆盖它。 例如,使用位置信息调用 Windows API MessageBox (它会恐慌哪个文件和行)。

到目前为止,我尝试了几种方法,每种方法都缺少一些东西。

  1. 编写我的自定义错误,并覆盖其Debug特征。 问题是这种错误类型需要能够包装任何底层错误(例如dyn std::error::Error ),以便我仍然可以编写
fn test() -> std::result::Result<(), CustomError> {
  ...
  if (has_windows_error) {
    return Err(WindowsError(123))?;
  }
  if (has_io_error) {
    return Err(IoError(123))?;
  }

  Ok(())
}

但是,这意味着 CustomError 需要同时实现std::error::ErrorFrom<std::error::Error> ,它们相互冲突。

  1. 编写我的自定义结果类型,并实现Try 这种方法需要接触实验性的#![feature(try_trait_v2)]

  2. 使用std::panic::set_panic_hook() ,然后永远不要使用? 在代码中。 相反,仅立即unwrap()所有Result 这是必需的,因为如果我允许错误冒泡,我将丢失PanicInfo中的位置信息。

我对 Rust 比较陌生,所以我可能会遗漏很多东西。 选项 3 是我目前正在使用的,尽管我不喜欢它迫使我放弃惯用的编码风格。

目前实现自定义错误输出的最干净、侵入性更小的方法是什么?

选项 3 肯定不是这里的方法。 在 Rust 中,恐慌意味着不可恢复的错误,根据我过去 2 年在社区中的经验,该指南被非常重视。 此外,选项 1 和 2 为操作添加了相当大的副作用,这些副作用从未打算隐藏这样的东西。

此外,我不确定“第 3 方库(例如无论如何)只会将错误消息打印到 stdout/stderr”是什么意思。 如果您的函数返回anyhow::Result<T>并且发生错误,那么所发生的就是错误被转换为anyhow::Error ,除非您打印它,否则它不会被打印。

底线是 Rust 中没有“错误处理框架”。 Results一点都不特别,实际上我鼓励您阅读源代码 如果您想以某种方式处理结果,则对其进行匹配并编写代码来处理它。 此外,恐慌处理机制并不意味着将它们提升为 C++ 异常之类的东西。 您可以在此处阅读有关其动机的更多信息。

听起来最适合您的是使用anyhow或类似的东西,并且在您的程序中的某个时刻,您可以匹配结果,转换您选择的anyhow::Error (或std::error::Error实现者) 到一个字符串并打开一个消息框。 如果您想包含有关错误发生位置的文件和行信息,则可以通过file! line! 通过标准库提供的宏。 这可能类似于以下内容:

pub fn main() {
    if let Err(error) = try_main() {
        // show_message_box implementation not shown
        show_message_box(error.to_string());
    }
}

pub fn try_main() -> anyhow::Result<()> {
    // code which makes extensive use of `?`
}

请注意,Rust 的错误处理方法与许多其他广泛使用的语言不同,因此需要改变编码风格。 错误是故意侵入您的代码,因此您实际上可以正确处理它们,随着时间的推移,我非常感激这一点。 事实上,Rust 的特性使它成为一种非常固执己见的语言,所以当你遇到痛点时,我建议不要尝试通过使用超出预期用途的语言特性来解决它们,因为这更有可能导致额外的痛点而不是解决你的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM