我想学习如何正确处理Rust中的错误.我读过这本书和这个例子 ; 现在我想知道我应该如何处理这个函数中的错误:
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
}
Run Code Online (Sandbox Code Playgroud)
这段代码不合适; 它会导致编译错误:
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
Run Code Online (Sandbox Code Playgroud)
处理这种情况的正确模式是什么?对我来说,reqwest::Error
在这种情况下是一个很好的解决方案,所以我想避免定义我自己的错误类型:
enum MyError {
Request(reqwest::Error),
Url(url::ParseError) // this already a part of request::Error::Kind!!!
}
Run Code Online (Sandbox Code Playgroud)
S.R*_*S.R 27
Rust 编程语言正在快速发展,因此可以添加新的答案!我真的很喜欢custom_error但现在我认为这thiserror
将是我所爱的人!
use thiserror::Error;
#[derive(Error, Debug)]
pub enum DataStoreError {
#[error("data store disconnected")]
Disconnect(#[from] io::Error),
#[error("the data for key `{0}` is not available")]
Redaction(String),
#[error("invalid header (expected {expected:?}, found {found:?})")]
InvalidHeader {
expected: String,
found: String,
},
#[error("unknown data store error")]
Unknown,
}
Run Code Online (Sandbox Code Playgroud)
这允许更改io::Error
为DataStoreError::Disconnect
带问号?
。去这里了解详情
有用的链接:
Vla*_*eev 16
不幸的是,在您的情况下reqwest::Error
,如果reqwest
库没有提供这样做的方法(并且可能没有),则无法从其他错误类型创建.要解决此问题,这是非常常见的,特别是在使用多个库的应用程序中,正确的解决方案将是以下之一:
使用应用程序使用的所有错误(或应用程序的一个子系统;粒度高度依赖于项目)声明您自己的自定义枚举,并声明From
从您使用的所有错误到此枚举类型的转换.
作为此方法的扩展,您可以使用error-chain
(或quick-error
基于错误链的基础)以半自动方式生成此类自定义类型和转换.
使用特殊的通用错误类型.基本上有两个:
一个.Box<Error>
在Error
标准库中定义的位置.
然后问号运算符将能够将任何兼容的错误转换为这些类型之一,因为各种Into
和From
特征实现.
请注意,failure
箱子旨在将定义在锈社区推广的错误方式.它不仅提供了一个常见的错误类型和特征(它修复了std::error::Error
特征的各种问题;例如参见此处),它还具有定义您自己的错误类型的工具(例如,使用failure_derive
),以及跟踪错误上下文,原因并生成回溯.此外,它会尝试与现有的错误处理方法尽可能兼容,因此它可以用来与使用其他,较旧的方法(库集成std::error::Error
,error-chain
,quick-error
)很容易.所以我强烈建议你先考虑使用这个箱子,然后再考虑其他选择.
我已经开始failure
在我的应用程序项目中使用,而我无法表达错误处理变得更容易和更好.我的方法如下:
定义Result
类型:
type Result<T> = std::result::Result<T, failure::Error>;
Run Code Online (Sandbox Code Playgroud)使用Result<Something>
无处不在可以返回一个错误,使用问号运算符(?
)错误和功能之间的转换像err_msg
或format_err!
或bail!
创建自己的错误消息.
我还没有使用编写库failure
,但我想对于库来说,创建更多特定的错误声明为枚举是很重要的,这可以通过failure_derive
crate 来完成.但是对于应用程序来说,failure::Error
类型绰绰有余.
在这种情况下,无法重用基础错误类型,因为您无法构造其隐藏字段。即使有可能,我也会建议不要这样做,以便使您的代码更加灵活且面向未来。
定义自定义错误类型可能需要编写大量样板文件,但幸运的是,有几个库可以减轻这种痛苦。上面已经提到了failure、error-chain和fast-error,但我想向您指出我写的一个板条箱,它比其他板条箱涉及更少的样板:custom_error。有了它,你可以写:
#[macro_use] extern crate custom_error;
custom_error!{ MyError
Request{source: reqwest::Error} = "request error",
Url{source: url::ParseError} = "invalid url"
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4814 次 |
最近记录: |