合并两种错误类型最惯用的方法是啥?
Posted
技术标签:
【中文标题】合并两种错误类型最惯用的方法是啥?【英文标题】:What is the most idiomatic way to merge two error types?合并两种错误类型最惯用的方法是什么? 【发布时间】:2019-02-25 14:00:47 【问题描述】:我有一个类型 Foo
,其方法可能会“引发”关联类型 Foo::Err
的错误。
pub trait Foo
type Err;
fn foo(&mut self) -> Result<(), Self::Err>;
我有另一个特征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>;
第二个将两种错误类型合并到一个专用的枚举中:
pub trait Bar2
type Err;
fn bar<F: Foo>(&mut self, foo: F) -> Result<F, Choice<F::Err, Self::Err>>;
第二个在语义上看起来更清晰,但为处理额外的枚举带来了一些障碍。
playground
【问题讨论】:
【参考方案1】:您应该使用 trait 对象 Error
,然后返回遇到的第一个错误:
pub trait Bar
fn bar<F: Foo>(&mut self, foo: F) -> Result<F, Box<dyn Error>>;
或者像这样实现你的特质:
impl Bar for MyType
type Err = Box<dyn Error>;
fn bar<F: Foo>(&mut self, foo: F) -> Result<F, Self::Err>;
如果你真的想有两个错误(但这很奇怪,因为一个错误就足以使过程不正常),你可以使用像 failure
这样的板条箱来创建一个“错误跟踪”。
作为一般建议,您不应忘记使用 std
中的特征来为您的代码添加更多语义。
【讨论】:
@trentcl 哦,你是对的,Err 之后就没用了:P 谢谢你的评论。 关于错误特征的好点,这确实是我必须使用的东西。实际上,这打开了返回 BoxError
types in Rust? 以获取选定替代方案的列表。【参考方案2】:
通常您不会执行“合并”,而是使用嵌套错误,就像这样。
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)
【讨论】:
对不起,如果我的例子不清楚;当我写到“将两个错误 types 合并到一个专用枚举中”时,我想到的就是你的GenericError
。我的问题是:这个附加层是正确的方法,还是我应该使用结果的结果?...以上是关于合并两种错误类型最惯用的方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
在 Vim 中,将文件中的所有行合并为一行的最简单方法是啥?