我正在使用 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
在我看来,这些在语义上是等价的,那么这是怎么回事呢?我显然遗漏了一些东西,并且希望您能指出正确的方向。
您需要使用
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 };