首页 > 解决方案 > 如果 Result 在 Vector 中,如何获取 Result 的 Ok 值?

问题描述

#[derive(Debug)]
struct S{}

#[derive(Debug)]
struct E{}

fn test() -> Result<S, E> {
    let data_1: Result<S, E> = Ok(S{});
    let data_2: Result<S, E> = Err(E{});
    let v: Vec<Result<S, E>> = vec![data_1, data_2];

    for i in 1..2 {
        for item in &v {
            let val = item?; //error
            println!("{:?}", val);
        };
    }

    Ok(S{})
}

在上面的代码中,如果 Result 是 Ok(否则返回 Err),我想打印 item 的值。(*item)?但是由于在共享引用后面移动了一个值,部分原因会出现错误:

[rustc E0507] [E] cannot move out of *itemwhich is behind a shared reference move because *itemhas type std::result::Result<tests::S, tests::E>, which does not implement the Copytrait

我已经尝试克隆数据,但它并没有解决问题。此外,克隆听起来也不正确。

什么是正确的解决方法/最佳实践?

标签: rust

解决方案


可以格式化引用(例如&S)。但是,?操作员需要在结果中返回错误,因此您必须复制、克隆或移动它:

复制

如果你Copy为你的类型实现了 trait,你可以取消引用&Result<S, E>playground):

#[derive(Debug, Copy, Clone)]
struct S {}

#[derive(Debug, Copy, Clone)]
struct E {}

Copy如果错误类型实现,但不是 ok 类型(游乐场) ,您也可以使其工作。

克隆

如果您需要将引用转换为不是Copy. 示例(操场):

#[derive(Debug, Clone)]
struct S {}

#[derive(Debug, Clone)]
struct E {}

let val = item.clone()?;

您可以将其更改为仅在出现错误时克隆(游乐场):

#[derive(Debug)]
struct S {}

#[derive(Debug, Clone)]
struct E {}

let val = item.as_ref().map_err(Clone::clone)?;

移动

如果在迭代后不需要向量,可以移动它:

for item in v {  // this calls `IntoIterator::into_iter(v)` implicitly
    let val = item?;
    println!("{:?}", val);
}

或者,您可以将 转换Vec<Result<S, E>>Result<Vec<S>, E>第一个:

// collects the `Ok` values, or returns the first error it encounters
let v: Vec<S> = v.into_iter().collect::<Result<_, _>>()?;

for item in &v {
    println!("{:?}", item);
}

推荐阅读