3 个版本 (破坏性更新)

0.3.0 2023年6月1日
0.2.0 2023年5月15日
0.1.0 2019年9月6日

Rust 模式 中排名 #1047

每月下载量 22

Apache-2.0

9KB
144

Except

唯一的 Error

目前仅在 nightly 工具链中可用。

为什么?

Rust 的官方错误处理方法是 Result<T, E> where E: Error

但是 Error 太复杂,各种类型需要转换,每个 crate 都有自己的 Error 集合。

更糟糕的是,会出现枚举嵌套,例如

enum BazError {
    IO(std::io::Error),
}

enum BarError {
    IO(std::io::Error),
    Baz(BazError),
}

enum FooError {
    IO(std::io::Error),
    Bar(BarError),
}

这里出现了多少次 std::io::Error

anyhow::Error 很好,但它通常只用于应用。

解决方案

这只是个人观点。

实际上,Error 只包含以下元素

  • type:自动生成的 id,用于确定 Error 是否为某种类型。
  • sub_type:自动生成的 id,用于确定 Error 是否为某种子类型,用于补充类型。
  • message:描述 Error 的字符串。
  • data:可选的 Error 数据。
  • backtrace:Error 调用栈。
  • source:可选的前一个 Error。

对于 Rust,messagebacktracesource 已存在于 std::error::Error 中。

因此,我更喜欢自动生成 type,我认为 TypeId 是一个解决方案。

对于 data,我没有最好的想法,因为它的类型可能各不相同。为了实现只有一个 Error,我选择在内部使用 Box<dyn Any> 来保存它。

示例

use except::ErrorBuilder;

pub struct MyErrorKind;

pub fn foo() -> except::Result<()> {
    Err(ErrorBuilder::new::<MyErrorKind>().message("this is my error").build())
}

pub fn main() {
    if let Err(ex) = foo() {
        if ex.is::<MyErrorKind>() {
            eprintln!("my error detected: {:?}", ex);
        }
    }
}

许可证

Apache-2.0

无运行时依赖