rust 如何将Future作为函数参数传递?

brccelvz  于 2023-01-13  发布在  其他
关注(0)|答案(2)|浏览(174)

我习惯了Scala的Future类型,在Future[..]类型中,您可以 Package 要返回的任何对象,以指定它。
我的Rust函数hello返回了Query,但我似乎无法将该结果作为Future<Output = Query>类型的参数传递。为什么不能?我应该如何更好地键入它?
当我试图将未来作为一个参数传递时,失败发生了:

use std::future::Future;

struct Person;
struct DatabaseError;

type Query = Result<Vec<Person>, DatabaseError>;

async fn hello_future(future: &dyn Future<Output = Query>) -> bool {
    future.await.is_ok()
}

async fn hello() -> Query {
    unimplemented!()
}

async fn example() {
    let f = hello();
    hello_future(&f);
}

fn main() {}

它编译失败,并出现错误:

error[E0277]: `&dyn Future<Output = Result<Vec<Person>, DatabaseError>>` is not a future
 --> src/main.rs:9:5
  |
9 |     future.await.is_ok()
  |     ^^^^^^^^^^^^ `&dyn Future<Output = Result<Vec<Person>, DatabaseError>>` is not a future
  |
  = help: the trait `Future` is not implemented for `&dyn Future<Output = Result<Vec<Person>, DatabaseError>>`
  = note: required by `poll`
gstyhher

gstyhher1#

async函数经过去糖处理,返回一个实现Future trait的opaque值。这意味着你可以接受一个实现该trait的泛型类型。最简洁的语法是impl Trait,但是你也可以引入一个命名的泛型参数:

async fn hello_future(future: impl Future<Output = Query>) -> bool {
    future.await.is_ok()
}

async fn example() {
    let f = hello();
    hello_future(f);
}

另见:

os8fio9y

os8fio9y2#

也可以使用Pin<Box<dyn Future<Output = Query>>>作为参数:

async fn hello_future(future: Pin<Box<dyn Future<Output = Query>>>) -> bool {
    future.await.is_ok()
}
...
async fn example() {
    let f: impl Future<Output = Result<Vec<Person>, DatabaseError>> = hello();
    hello_future(Box::pin(f));
}

不同之处在于impl Future是编译时分派,编译器为hello_future的每个类型示例化生成可执行代码,而Pin<Box<...>>是运行时分派,只为hello_future生成可执行二进制代码的一个副本。

相关问题