首页 > 解决方案 > 如何解决 Rust 在方法设计中的“使用移动值”?

问题描述

我有一个系统,它将连接多个 API 下游。我想用

let mut system = System::new()

接收配置并进行验证,然后用于 system.init() 初始化下游的所有连接。在它连接所有下游之后,我想做多种方法对下游进行 CRUD。

这里是游乐场

struct Conn {
    connection: String,
}
impl Conn {
    fn fetch(&mut self) -> &str {
        self.connection.push_str("data");
        &self.connection
    }
}

struct System {
    downstream: Option<Conn>,
}

impl System {
    fn new() -> Self {
        System { downstream: None }
    }

    fn init(&mut self) {
        self.downstream = Some(Conn {
            connection: String::from("db connection"),
        })
    }

    fn method_a(self) -> String {
        let mut conn = self.downstream.unwrap();
        String::from(conn.fetch())
    }
    fn method_b(self) -> String {
        let mut conn = self.downstream.unwrap();
        String::from(conn.fetch())
    }
}

fn main() {
    let mut system = System::new();
    system.init();

    println!("{}", system.method_a());
    println!("{}", system.method_b());
}

但是,由于system.method_a()将所有权移至unwrap(),所以当我在第一个方法之后调用第二个方法时system.method_b()。显然,我会得到“使用移动值”的错误。

我了解错误发生的方式和原因。但我不知道处理这种情况的惯用方法是什么。

一种解决方法是使用Conn而不是Option<Conn>,但如果不使用选项,那么我必须初始化所有下游连接,System.new()并且所有下游不能具有“无”的值。

所以我的问题是我如何设计一个模块来解决我的目的?

提前致谢。

标签: rust

解决方案


在您提供的示例中,您可以更改method_amethod_b改为采用可变引用。conn本身只是调用fetch()使用可变引用的。

fn method_a(&mut self) -> String {
    self.downstream
        .as_mut()
        .map(|conn| String::from(conn.fetch()))
        .unwrap()
}

fn method_b(&mut self) -> String {
    self.downstream
        .as_mut()
        .map(|conn| String::from(conn.fetch()))
        .unwrap()
}

操场

出于理解的目的,您还可以将上述方法编写为:

fn method_a(&mut self) -> String {
    match self.downstream {
        Some(ref mut conn) => String::from(conn.fetch()),
        None => panic!(),
    }
}

操场

如果上面的代码只是一个示例片段,并且conn由于某种原因您需要所有权,您可以这样做,take()如果这也不起作用,那么您将不得不使您的结构实现Clone特征,以便您可以克隆它而不是移动.


推荐阅读