将变量传递到 Rust FnMut 而不使其变成 FnOnce

问题描述 投票:0回答:1

我正在尝试更改 Rust Tonic UDS gRPC 客户端示例。它包含以下代码块(请参阅链接):

let channel = Endpoint::try_from("http://[::]:50051")?
    .connect_with_connector(service_fn(|_: Uri| async {
        let path = "/tmp/tonic/helloworld";

         // Connect to a Uds socket
        Ok::<_, std::io::Error>(TokioIo::new(UnixStream::connect(path).await?))
    }))
    .await?;

更改非常简单:我只想能够从外部传入

path
而不是将其设置为固定值。问题是,它要么抱怨
service_fn
内部的函数比在其外部定义的任何
path
对象寿命更长。或者,如果我使用
move
传递它,它会抱怨
service_fn
需要一个
FnMut
,但现在我们给它一个
FnOnce

这两个错误对我来说都是有意义的:在我们超出了在该方法外部定义的任何

path
对象的生命周期之后很久,就可以从单独的线程调用该方法。而且,如果我们将其移动到函数中,则该移动只能完成一次,因此该函数不能再被多次调用,因为它可能需要为多个请求提供服务。

我在这里找到了一个答案,似乎完全符合我的需要,但我就是无法让它工作。我确信我错过了一些明显的东西,但我就是不知道它是什么。

rust lifetime
1个回答
0
投票

您应该能够通过闭包

path
来捕获外部
move
变量。 到那时,你能用
path
做什么取决于未来的生命周期是如何限制的。 例如,这可能有效:

let move = todo!();

let channel = Endpoint::try_from("http://[::]:50051")?
    .connect_with_connector(service_fn(move |_: Uri| async {
        // Connect to a Uds socket
        Ok::<_, std::io::Error>(TokioIo::new(UnixStream::connect(&path).await?))
    }))
    .await?;

但是,可能不会,因为未来可能不会被限制在关闭之后继续存在。 如果是这种情况,那么您需要将通往未来的路径的克隆移交给:

let move = todo!();

let channel = Endpoint::try_from("http://[::]:50051")?
    .connect_with_connector(service_fn(move |_: Uri| {
        let path = path .clone();
        async move {
            // Connect to a Uds socket
            Ok::<_, std::io::Error>(TokioIo::new(UnixStream::connect(path).await?))
        }
    }))
    .await?;
© www.soinside.com 2019 - 2024. All rights reserved.