同时匹配Result :: Err或Result :: Ok内部的可选字段

时间:2019-02-27 21:43:13

标签: rust mapping match

我有一个结构是API端点,所以我不能更改其结构

struct Response {
    error: Option<String>,
    results: Vec<String>,
}

如果errorSome,则表示服务器端发生故障。

我有一个返回结构的函数:

fn get_results() -> Result<Response, String> {
    unimplemented!()
}

是否可以在同一get_results分支中匹配Result Response.error错误和可选的match

这是我的尝试

fn example() {
    let ret = get_results();
    match ret.map(|resp| resp.error.map_or_else(|| Ok(resp.results), |e| Err(e))) {
        Err(e) => {
            println!("Error: {}", &e);
        }
        Ok(results) => {
            //Handle results
        }
    }
}

但是失败了:

error[E0382]: use of moved value: `resp`
  --> src/lib.rs:12:49
   |
12 |     match ret.map(|resp| resp.error.map_or_else(|| Ok(resp.results), |e| Err(e))) {
   |                          ----------             ^^    ---- use occurs due to use in closure
   |                          |                      |
   |                          |                      value used here after move
   |                          value moved here
   |
   = note: move occurs because `resp.error` has type `std::option::Option<std::string::String>`, which does not implement the `Copy` trait

2 个答案:

答案 0 :(得分:3)

您可以将响应转换为如下结果:

match resp.error {
    Some(e) => Err(e),
    None => Ok(resp.results),
}

您可以使用and_then展平嵌套结果。放在一起,它给出了这一点:

ret.and_then(|resp| match resp.error {
    Some(e) => Err(e),
    None => Ok(resp.results),
})

答案 1 :(得分:2)

如果错误字段是公开的,则可以执行以下操作:

match resp {
    Err(s) | Ok(Response { error: Some(s), .. }) => println!("Error: {}", s),
    Ok(Response { error: None, results }) => println!("Responses: {:?}", results)
}

这显示了Rust的match语句有多么强大。

Playground of a simplified example