假设我有一些数据Bar(例如数据库客户端),我只想创建一次 但对于我的 struct Foo来说是懒惰的.

struct Bar;

struct Foo {
    bar: Option<Bar>
}

为此,我判断该字段是否已初始化;如果未初始化,则运行异步 routine . 然后将 routine 的结果保存为Some以供以后重复使用.

我知道,这Option::get_or_insert_with美元完全符合这种情况,但我必须 处理异步操作,所以我像这样手动操作.

impl Foo {
    pub async fn get_bar(&mut self) -> &Bar {
        if let Some(bar) = &self.bar {
            return bar;
        }
        
        let bar = Self::create_bar().await;
        self.bar.insert(bar)
    }
    
    /// Long and heavy-resource routine,
    /// we want to memoize it.
    async fn create_bar() -> Bar {
        Bar
    }
}

然而,由于不变的andself.bar的可变borrow ,这不能被编译. 有什么方法可以正确地做到这一点吗?

Full example.

推荐答案

有趣的是,借入判断器能够通过在你的if let中使用ref关键字来推断更长的使用生命周期 ,所以下面的works:

    pub async fn get_bar(&mut self) -> &Bar {
        if let Some(ref bar) = self.bar {
            return bar;
        }
        let bar = Self::create_bar().await;
        self.bar.insert(bar)
    }

Rust相关问答推荐

为什么迭代器上的`. map(...)`的返回类型如此复杂?

异步FN中的 rust 递归

支持TLS的模拟HTTP服务器

如何为rust trait边界指定多种可能性

使用Box优化可选的已知长度数组的内存分配

如何点击()迭代器?

JSON5中的变量类型(serde)

对reqwest提供的这种嵌套JSON struct 进行反序列化

可以在旋转循环中调用try_recv()吗?

如何从borrow 的异步代码运行阻塞代码?

如何在Rust中使用Serde创建一个自定义的反序列化器来处理带有内部标记的枚举

我如何取消转义,在 Rust 中多次转义的字符串?

Rust 中的自动取消引用是如何工作的?

没有得到无法返回引用局部变量`queues`的值返回引用当前函数拥有的数据的值的重复逻辑

使用自定义 struct 收集 Vec

如何展平以下嵌套的 if let 和 if 语句?

为什么我可以从读取的可变自引用中移出?

编写 TOML 文件以反序列化为 struct 中的枚举

在 Rust 中有条件地导入?

如何在宏中的多个参数上编写嵌套循环?