为什么当我将闭包存储为变量时会出现生命周期错误,而当我将其声明为表达式时却没有错误?

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

我正在使用 AWS Lambda(通过 lambda_http 板条箱),并且以下代码无法编译:

let handler = service_fn(move |event: Request| async  {
    handler_organization_post(&shared_client, event).await
});
lambda_http::run(handler).await
error: lifetime may not live long enough
   --> organization/organization_post/src/main.rs:125:52
    |
125 |       let handler = service_fn(move |event: Request| async  {
    |  ______________________________---------------------_^
    | |                              |                   |
    | |                              |                   return type of closure `[async block@organization/organization_post/src/main.rs:125:52: 127:6]` contains a lifetime `'2`
    | |                              lifetime `'1` represents this closure's body
126 | |         handler_organization_post(&shared_client, event).await
127 | |     });
    | |_____^ returning this value requires that `'1` must outlive `'2`
    |
    = note: closure implements `Fn`, so references to captured variables can't escape the closure

但是,如果我只是将闭包声明内联到对

lambda_http::run
的调用中,则程序编译并运行时不会出现任何问题:

lambda_http::run(service_fn(move |event: Request| async move {
    handler_organization_post(&shared_client, event).await
})).await

在我看来,这些在语义上是等价的,那么这是怎么回事呢?我显然遗漏了一些东西,并且希望您能指出正确的方向。

rust aws-lambda closures
1个回答
0
投票

您需要使用

async move
才能使闭包有效。这是代码的两个版本之间的区别 - 第二个版本使用
async move
,而第一个版本则没有。

要理解这一点,请回想一下

async
块会计算为
impl Future
- 实现
Future
特征的某个值。块内的代码不会立即执行。它仅在“轮询”未来时执行 - 也就是说,当有人尝试评估未来并获取潜在价值时。

考虑使用

async
的一个非常简单的闭包。

let closure = |y: i32| async { y + 1 };

这实际上不是一个有效的闭包。

async
块没有
move
关键字,因此它求值的 future 包含对
y
的引用,而不是
y
本身。当
async
块被求值时,该引用将不再有效,因为闭包将返回。为了使一切正常工作,您需要将代码更改为

let closure = |y: i32| async move { y + 1 };
© www.soinside.com 2019 - 2024. All rights reserved.