rust 同时匹配Result::Err或Result::Ok中的可选字段

7rfyedvj  于 2024-01-08  发布在  其他
关注(0)|答案(3)|浏览(113)

我有一个作为API端点的结构,因此无法更改其结构

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

字符串
如果errorSome,这意味着它在服务器端失败。
我有一个函数返回结构体:

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


是否可以在同一个match分支中匹配get_resultsResult错误和可选的Response.error
这是我的尝试:

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

xzlaal3s

xzlaal3s1#

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

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),
})

jtjikinw

jtjikinw2#

如果error字段是public,你可以这样做:

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

ie3xauqp

ie3xauqp3#

使用2021年的Rust版本,您的程序现在按原样运行。
尽管如此,我还是更喜欢let-else语法,因为它使程序更清晰:

fn example() {
    let ret = get_results();
    let Ok(results) = ret else { println!("Error: {}", ret.err().unwrap()); return; };
    // handle results here…
}

字符串

相关问题