我正在try 创建一个Futures中的Vec,以便与try_join_all一起使用.

use futures::future::try_join_all;

struct Image {
    pub file_name: String,
}

struct Storage;

impl Storage {
    async fn upload(&self, filename: &str) -> Result<String, ()> {
        Ok(filename.to_owned())
    }
}

struct ImagesRepository {
    storage: Storage,
}

impl ImagesRepository {
    async fn upload_images(&self, images: &[Image]) -> Result<Vec<String>, ()> {
        let futures = images
            .iter()
            .map(|image| {
                let path_name = format!("somedirectory/{}", &image.file_name);

                let future = self.storage.upload(path_name.as_str());

                future
            })
            .collect::<Vec<_>>();

        let results = try_join_all(futures).await?;

        Ok(results)
    }
}

但是,我收到以下编译器错误:

   Compiling playground v0.0.1 (/playground)
error[E0515]: cannot return value referencing local variable `path_name`
  --> src/lib.rs:30:17
   |
26 |                 let future = self.storage.upload(path_name.as_str());
   |                                                  ------------------ `path_name` is borrowed here
...
30 |                 future
   |                 ^^^^^^ returns a value referencing data owned by the current function

For more information about this error, try `rustc --explain E0515`.
error: could not compile `playground` due to previous error

这是因为我向storage.upload传递了一个对path_name的引用,它只存在于闭包中.

我知道我可以将storage.upload改为String,但这意味着要破解使用此函数的其他部分的代码.

有没有办法修复这个编译器错误?

Minimal example - Rust Playground

推荐答案

这实际上是相当简单的.你只需要把future 包裹在另一个拥有这根线的future 里.您可以使用async块来实现这一点,它用于创建即席匿名Future实施值(就像|...|可用于创建临时匿名Fn*实现值一样):

.map(|image| async {
    let path_name = format!("somedirectory/{}", &image.file_name);

    self.storage.upload(path_name.as_str()).await
})

(Playground)

创造一个future ,然后从它返回等待另一个future 的结果,这通常是一种反模式,但这是不是这样的情况之一.这是因为包装器future 不只是代理内部future 的现成值,它还负责在内部future 准备好后运行path_name的析构函数.


如果您愿意,甚至可以完全删除path_name变量:

.map(|image| async {
    self.storage.upload(
        &format!("somedirectory/{}", &image.file_name)
    ).await
})

Rust相关问答推荐

有没有方法处理rust中嵌套的ok_or()?

Rust中的相互递归特性与默认实现

trait声明中的生命周期参数

我怎样才能从一个Rust 的日期中go 掉3年?

当第二个`let`依赖于第一个`let()`时,如何在一行中有多个`let()`?

如何将像烫手山芋一样不透明的值从一个Enum构造函数移动到下一个构造函数?

无法从流中读取Redis请求

为什么AsyncRead在Box上的实现有一个Unpin特征绑定?

为什么不';t(&;mut-iter).take(n)取得iter的所有权?

通过异常从同步代码中产生yield 是如何工作的?

将泛型中的 Box 转换为 rust 中的 Box

如何在 Rust 中将 Vec> 转换为 Vec>?

切片不能被 `usize` 索引?

为什么在 macOS / iOS 上切换 WiFi 网络时 reqwest 响应会挂起?

使用 HashMap 条目时如何避免字符串键的短暂克隆?

当我不满足特征界限时会发生什么?

在 FFI 的上下文中,未初始化是什么意思?

为什么基于 clap::Parser 读取的大量数字进行计算比硬编码该数字时慢?

A 有一个函数,它在 Option<> 类型中时无法编译,但在 Option<> 类型之外会自行编译.为什么?

您不能borrow 对只读值的可变引用