我想学习如何正确地处理Rust中的错误。我已经阅读了book和这个例子;现在我想知道我应该如何处理这个函数中的错误:
fn get_synch_point(&self) -> Result<pv::synch::MeasPeriods, reqwest::Error> {
let url = self.root.join("/term/pv/synch"); // self.root is url::Url
let url = match url {
Ok(url) => url,
// ** this err here is url::ParseError and can be converted to Error::Kind https://docs.rs/reqwest/0.8.3/src/reqwest/error.rs.html#54-57 **//
Err(err) => {
return Err(Error {
kind: ::std::convert::From::from(err),
url: url.ok(),
})
}
};
Ok(reqwest::get(url)?.json()?) //this return reqwest::Error or convert to pv::sych::MeasPeriods automaticly
}
此代码不正确;会导致编译错误:
error[E0451]: field `kind` of struct `reqwest::Error` is private
--> src/main.rs:34:42
|
34 | Err(err) => return Err(Error{kind: ::std::convert::From::from(err), url: url.ok()})
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `kind` is private
error[E0451]: field `url` of struct `reqwest::Error` is private
--> src/main.rs:34:81
|
34 | Err(err) => return Err(Error{kind: ::std::convert::From::from(err), url: url.ok()})
| ^^^^^^^^^^^^^ field `url` is private
处理这种情况的合适模式是什么?对我来说,reqwest::Error
在这种情况下是一个很好的解决方案,所以我希望避免定义自己的错误类型:
enum MyError {
Request(reqwest::Error),
Url(url::ParseError) // this already a part of request::Error::Kind!!!
}
5条答案
按热度按时间hsvhsicv1#
更新2020
Rust编程语言正在快速发展,所以可以添加新的答案!我真的很喜欢custom_error,但现在我认为
thiserror
将是我的爱人!这允许将
io::Error
更改为带有问号?
的DataStoreError::Disconnect
。有用链接:
thiserror
in combine withanyhow
其他有趣的板条箱:
对于恐慌:
falq053o2#
不幸的是,在您的情况下,如果
reqwest
库没有提供这样做的方法(很可能没有),您就不能从其他错误类型创建reqwest::Error
。要解决这个问题,特别是在使用多个库的应用程序中,正确的解决方案是以下之一:1.声明您自己的自定义枚举,其中包含应用程序处理的所有错误(或应用程序的一个子系统;粒度在很大程度上取决于项目),并声明从您处理的所有错误到该枚举类型的
From
转换。作为这种方法的扩展,您可以使用
error-chain
(或quick-error
,错误链基本上基于它)以半自动的方式生成这种自定义类型和转换。1.使用特殊的、通用的错误类型。基本上有两种类型:
a.
Box<Error>
,其中Error
在标准库中定义。B.使用
failure
机箱中定义的Error
类型。然后,问号操作符将能够将任何兼容错误转换为这些类型之一,因为
Into
和From
trait实现多种多样。请注意,
failure
crate是用来定义Rust社区中出现的错误的,它不仅提供了一个通用的错误类型和trait(修复了std::error::Error
trait的各种问题;例如,参见here),它还具有定义您自己的错误类型(例如,使用failure_derive
)以及用于跟踪错误上下文、原因和生成回溯的工具。此外,它尝试尽可能与现有的错误处理方法兼容,因此它可用于与使用其他较旧方法的库集成(std::error::Error
,error-chain
,quick-error
)相当容易。所以我强烈建议你先考虑使用这个板条箱,在其他选择之前。我已经开始在我的应用程序项目中使用
failure
,我无法表达错误处理变得多么容易和好。1.定义
Result
类型:1.在任何可能返回错误的地方使用
Result<Something>
,使用问号运算符(?
)在错误和err_msg
、format_err!
或bail!
等函数之间进行转换,以创建我自己的错误消息。我还没有用
failure
写过一个库,但是我想对于库来说,创建更具体的错误声明为枚举是很重要的,这可以用failure_derive
crate来完成,但是对于应用程序来说,failure::Error
类型已经足够了。soat7uwm3#
在这种情况下,重用底层错误类型是不可能的,因为你无法构造它的隐藏字段。即使可以重用底层错误类型,我也建议不要重用,以便让你的代码更灵活,更经得起未来的考验。
定义自定义错误类型可能需要编写大量的样板文件,但幸运的是,有几个库可以减轻这种痛苦。上面已经提到了 failure、error-chain 和 quick-error,但我想向您介绍我编写的一个板条箱,它比其他板条箱包含的样板文件更少:custom_error。使用它,您可以编写:
t98cgbkg4#
作为already stated by Vladimir Matveev,failure机箱应该是您的起点。
此错误枚举是可扩展的,这允许它适应将来可能对程序进行的修改。
2ekbmq325#
看来
anyhow
板条箱是好的,除了不支持Box<dyn StdError>
。大多数错误类型都实现了Display特征,所以请使用这个魔术。
1.自定义错误
1.从实现Display的所有对象实现From特征