标签: rust-result

当Iterator :: map返回Result :: Err时,如何停止迭代并返回错误?

我有一个函数返回一个Result:

fn find(id: &Id) -> Result<Item, ItemError> {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

然后另一个使用它像这样:

let parent_items: Vec<Item> = parent_ids.iter()
    .map(|id| find(id).unwrap())
    .collect();
Run Code Online (Sandbox Code Playgroud)

如何在任何map迭代中处理失败的情况?

我知道我可以使用flat_map,在这种情况下,错误结果将被忽略:

let parent_items: Vec<Item> = parent_ids.iter()
    .flat_map(|id| find(id).into_iter())
    .collect();
Run Code Online (Sandbox Code Playgroud)

Result迭代器有0或1个项目,具体取决于成功状态,flat_map如果为0则会过滤掉它.

但是,我不想忽略错误,我想改为使整个代码块停止并返回一个新错误(基于映射中出现的错误,或者只是转发现有错误).

如何在Rust中最好地处理这个问题?

rust rust-result

56
推荐指数
3
解决办法
7484
查看次数

如果成功,从函数返回错误的惯用方法是什么?

在Rust中,我认为处理可恢复错误的惯用方法是使用Result.例如,这个功能显然是惯用的:

fn do_work() -> Result<u64, WorkError> {...}
Run Code Online (Sandbox Code Playgroud)

当然,还有一些具有单一,明显的故障状态的功能,因此使用Option类型.一个惯用的例子是这样的:

fn do_work() -> Option<u64>
Run Code Online (Sandbox Code Playgroud)

这一切都在文档中直接解决.但是,我对函数可能失败的情况感到困惑,但在成功时没有任何有意义的值.比较以下两个功能:

fn do_work() -> Option<WorkError>
// vs
fn do_work() -> Result<(), WorkError>
Run Code Online (Sandbox Code Playgroud)

我只是不确定哪一个更惯用,或者更常用于现实世界的Rust代码.我这样的问题的首选资源是Rust书,但我不认为这是在" 错误处理 "部分中解决的.我也没有任何其他Rust文档的运气.

当然,这似乎是相当主观的,但我正在寻找权威的来源,要么说明哪种形式是惯用的,要么说明为什么一种形式优于(或劣等)另一种形式.(我也很好奇这个约定如何与其他大量使用"错误作为值"的语言相比,比如Go和Haskell.)

error-handling idiomatic optional rust rust-result

28
推荐指数
2
解决办法
5794
查看次数

使用结果迭代器最常用的方法是什么?

我有这样的代码:

let things = vec![/* ...*/]; // e.g. Vec<String>
things
    .map(|thing| {
        let a = try!(do_stuff(thing));
        Ok(other_stuff(a))
    })
    .filter(|thing_result| match *thing_result {
        Err(e) => true,
        Ok(a) => check(a),
    })
    .map(|thing_result| {
        let a = try!(thing_result);
        // do stuff
        b
    })
    .collect::<Result<Vec<_>, _>>()
Run Code Online (Sandbox Code Playgroud)

在语义方面,我想在第一个错误后停止处理.

上面的代码有效,但感觉非常麻烦.有没有更好的办法?我查看了类似的文档filter_if_ok,但我没有找到任何东西.

我知道collect::<Result<Vec<_>, _>>,它很有效.我特意试图消除以下样板:

  • 在过滤器的关闭,我必须使用matchthing_result.我觉得这应该只是一个单行,例如.filter_if_ok(|thing| check(a)).
  • 每次我使用时map,我都要包含一个额外的声明let a = try!(thing_result);,以便处理一个可能性Err.再一次,我觉得这可以被抽象出来.map_if_ok(|thing| ...).

有没有其他方法可以用来获得这种简洁程度,或者我只是需要强硬一点?

iterator filterfunction rust map-function rust-result

15
推荐指数
3
解决办法
1万
查看次数

是否可以将Option <Result <T,E >>转换为Result <Option <T>,E>而不使用匹配?

我首先想到的是mapOption的,但我不能用try!从封闭的内部.该match声明看起来是不必要的,但我无法弄清楚如何简化它.

fn example<T, E>(val: Option<Result<T, E>>) -> Result<Option<T>, E> {
    Ok(match val {
        Some(v) => Some(v?),
        None => None
    })
}
Run Code Online (Sandbox Code Playgroud)

optional rust rust-result

8
推荐指数
2
解决办法
730
查看次数

与仅返回 Ok() 分支相比,无误结果有什么意义?

Warp 拒绝处理程序的典型示例是

async fn handle_rejection(err: Rejection) -> Result<impl Reply, Infallible> {
Run Code Online (Sandbox Code Playgroud)

Result<ok, err>但是,这样的错误是绝对错误且永远无法达到的,有什么好处呢?为什么不直接返回一个impl Reply

rust warp rust-result

7
推荐指数
1
解决办法
4465
查看次数

dotenv().ok() 有什么作用?

我在 PostgreSQL 中使用 Diesel ORM 包装器。我正在关注他们网站上的指南,其中包含以下代码:

pub fn establish_connection() -> PgConnection {
     dotenv().ok();

     let database_url = env::var("DATABASE_URL")
         .expect("DATABASE_URL must be set");
     PgConnection::establish(&database_url)
         .expect(&format!("Error connecting to {}", database_url))
}
Run Code Online (Sandbox Code Playgroud)

dotenv()通过 dotenv 文档了解了它的作用 - 它加载了 env 文件。在源代码中,我看到它dotenv()返回一个Result. 那ok()做什么呢?它是否解开结果?如果是这样,为什么不使用unwrap()

rust rust-result

6
推荐指数
1
解决办法
1046
查看次数

在没有 map_err 的情况下使用 and_then 与不同的结果错误类型

我有一些函数会在失败时返回不同的错误类型。

首先,我有一个构建器,其中包含此方法:

#[derive(Debug)]
pub enum BuilderError {
    ElementMissing(&'static str),
}

pub fn spawn(self) -> Result<ServiceStatus, BuilderError>
Run Code Online (Sandbox Code Playgroud)

所以它会BuildError在失败时返回一个。

现在,我有另一个函数会返回另一个错误:

#[derive(Debug)]
pub enum XmlError {
    XmlCreationFailed(writer::Error),
    ConversionToUtf8(FromUtf8Error),
}

pub fn create_xml(service_status: super::ServiceStatus) -> Result<String, XmlError>
Run Code Online (Sandbox Code Playgroud)

这个想法是我使用构建器创建一个ServiceStatus对象并使用它来创建一个带有create_xml函数的 XML 字符串。

为此,我有以下代码:

#[derive(Debug)]
pub enum WebserviceError {
    XmlError(XmlError),
    BuilderError(BuilderError),
}

impl std::error::Error for WebserviceError {
    ...
}

impl From<XmlError> for WebserviceError {
    fn from(error: XmlError) -> WebserviceError {
        WebserviceError::XmlError(error)
    }
}

impl From<BuilderError> for WebserviceError {
    fn from(error: BuilderError) …
Run Code Online (Sandbox Code Playgroud)

rust rust-result

5
推荐指数
2
解决办法
1775
查看次数

确定类型时match和unwrap_or之间的区别

以下是我可以使用Rust 1.23.0编译的有效文件:

fn main() {
    let r = String::from("a");
    let a = Some(&r);
    let b = match a {
        Some(name) => name,
        None => "",
    };
    println!("{}", b);
}
Run Code Online (Sandbox Code Playgroud)

虽然下面的代码

fn main() {
    let r = String::from("a");
    let a = Some(&r);
    let b = a.unwrap_or("");
    println!("{}", b);
}
Run Code Online (Sandbox Code Playgroud)

错误失败:

fn main() {
    let r = String::from("a");
    let a = Some(&r);
    let b = match a {
        Some(name) => name,
        None => "",
    };
    println!("{}", b);
}
Run Code Online (Sandbox Code Playgroud)

据我所知,编译器在此处确定类型时的推理如下:

  1. 在使用a的情况下,match确定 …

generics option rust rust-result

5
推荐指数
1
解决办法
199
查看次数

如何将 Rust Result&lt;T, E&gt; 的错误泛化为 Result&lt;T, Box&lt;dyn std::error::Error&gt;&gt;?

我正在尝试泛化函数Result返回的a reqwest::blocking::get。它返回 aResult<reqwest::blocking::Response, reqwest::Error>但调用它的函数返回 a Result<reqwest::blocking::Response, Box<dyn std::error::Error>

  • 为什么我的第一次尝试无法编译?
  • 进行这种转换的最惯用的方法是什么?

这是第一次尝试:

fn get_example_fails() -> Result<Response, Box<dyn Error>> {
        let result = blocking::get("http://example.com");
        result.map_err(|error| Box::new(error))
    }

Run Code Online (Sandbox Code Playgroud)

它有以下错误,我不知道如何修复,但觉得通过一些小的调整可能会更惯用 - 但我不确定要调整什么:

error[E0308]: mismatched types
   --> src/bittrex.rs:143:9
    |
141 |     fn get_example_fails() -> Result<Response, Box<dyn Error>> {
    |                               -------------------------------- expected `Result<reqwes
t::blocking::Response, Box<(dyn StdError + 'static)>>` because of return type
142 |         let result = blocking::get("http://example.com");
143 |         result.map_err(|error| Box::new(error))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn StdError`, 
found …
Run Code Online (Sandbox Code Playgroud)

rust reqwest rust-result

4
推荐指数
1
解决办法
3742
查看次数

无法调用返回结果的函数:找到不透明类型 impl std::future::Future

我无法从 a 返回函数的结果Result。每个教程只展示如何使用 Result,而不展示如何从中返回值。

fn main(){
    let mut a: Vec<String> = Vec::new();
    a = gottem();
    println!("{}", a.len().to_string());
    //a.push(x.to_string()
}
async fn gottem() -> Result<Vec<String>, reqwest::Error> {
    let mut a: Vec<String> = Vec::new();
    let res = reqwest::get("https://www.rust-lang.org/en-US/")
        .await?
        .text()
        .await?;
    Document::from(res.as_str())
        .find(Name("a"))
        .filter_map(|n| n.attr("href"))
        .for_each(|x| println!("{}", x));
    Ok(a)
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

fn main(){
    let mut a: Vec<String> = Vec::new();
    a = gottem();
    println!("{}", a.len().to_string());
    //a.push(x.to_string()
}
async fn gottem() -> Result<Vec<String>, reqwest::Error> {
    let mut a: Vec<String> = Vec::new();
    let …
Run Code Online (Sandbox Code Playgroud)

rust reqwest rust-result

3
推荐指数
1
解决办法
4183
查看次数