Pie*_*ine 5 error-handling idioms rust
我有一个类型,Foo它的方法可能会“引发”相关类型的错误Foo::Err。
pub trait Foo {
type Err;
fn foo(&mut self) -> Result<(), Self::Err>;
}
Run Code Online (Sandbox Code Playgroud)
我有另一个特性,它Bar有一个方法来处理Foo. Bar可能会发出自己的错误(由关联类型指定Bar::Err),但也可能会遇到由Foo它正在处理的生成的错误。
我可以看到两种方法来做到这一点,但我不知道哪一种最适合 Rust。
第一个将结果嵌入到结果中:
pub trait Bar1 {
type Err;
fn bar<F: Foo>(&mut self, foo: F) -> Result<Result<F, F::Err>, Self::Err>;
}
Run Code Online (Sandbox Code Playgroud)
第二个将两种错误类型合并到一个专用的枚举中:
pub trait Bar2 {
type Err;
fn bar<F: Foo>(&mut self, foo: F) -> Result<F, Choice<F::Err, Self::Err>>;
}
Run Code Online (Sandbox Code Playgroud)
第二个在语义上看起来更清晰,但为处理额外的枚举创建了一些障碍。
通常你不做“合并”,而是使用嵌套错误,就像这样。
enum IntError {
Overflow,
Underflow
}
enum StrError {
TooLong,
TooShort,
}
enum GenericError {
Int(IntError),
Str(StrError),
}
impl From<IntError> for GenericError {
fn from(e: IntError) -> Self {
GenericError::Int(e)
}
}
impl From<StrError> for GenericError {
fn from(e: StrError) -> Self {
GenericError::Str(e)
}
}
Run Code Online (Sandbox Code Playgroud)
您应该使用特征对象Error,并返回遇到的第一个错误:
pub trait Bar {
fn bar<F: Foo>(&mut self, foo: F) -> Result<F, Box<dyn Error>>;
}
Run Code Online (Sandbox Code Playgroud)
或者像这样实现你的特质:
impl Bar for MyType {
type Err = Box<dyn Error>;
fn bar<F: Foo>(&mut self, foo: F) -> Result<F, Self::Err>;
}
Run Code Online (Sandbox Code Playgroud)
如果你真的想要有两个错误(但这很奇怪,因为一个错误足以使过程不正常),你可以使用一个板条箱failure来创建一个“错误跟踪”。
作为一般建议,您不应忘记使用 from 的特征std来为代码添加更多语义。