如何将异步函数存储在结构中并从结构实例中调用它?

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

我正在尝试使用新的async / await语法,std::future::Future和最近的Tokio版本来实现。我正在使用Tokio 0.2.0-alpha.4和Rust 1.39.0-nightly

我尝试过的其他事情包括:

  • 对要存储在结构中的类型使用Box<dyn>
  • 在结构定义中使用泛型

我无法获得最低的工作版本,所以这是我要实现的目标的简化版本:

async fn foo(x: u8) -> u8 {
    2 * x
}

// type StorableAsyncFn = Fn(u8) -> dyn Future<Output = u8>;

struct S {
    f: StorableAsyncFn,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let s = S { f: foo };

    let out = (s.f)(1).await;

    Ok(())
}

[StorableAsyncFn在这里未定义,这是我尝试定义的类型。

因此,此代码当然无法编译,并出现以下错误:

error[E0412]: cannot find type `StorableAsyncFn` in this scope
asynchronous struct rust async-await future
1个回答
0
投票

让我们以此作为我们的Minimal, Reproducible Example

async fn foo(x: u8) -> u8 {
    2 * x
}

struct S {
    foo: (),
}

async fn example() {
    let s = S { foo };
}

它产生错误:

error[E0308]: mismatched types
  --> src/main.rs:10:17
   |
10 |     let s = S { foo };
   |                 ^^^ expected (), found fn item
   |
   = note: expected type `()`
              found type `fn(u8) -> impl std::future::Future {foo}`

foo的类型是一个函数指针,它使用u8并返回实现特征std::future::Future的某种类型。 async fn实际上只是将-> Foo转换为-> impl Future<Output = Foo>的语法糖。

我们将结构设为泛型,并在匹配的泛型上放置一个特征绑定。在实际代码中,您可能想对Output关联类型施加约束,但此示例不需要。然后,我们可以像调用其他任何可调用成员字段一样调用该函数:

async fn foo(x: u8) -> u8 {
    2 * x
}

struct S<F>
where
    F: std::future::Future,
{
    foo: fn(u8) -> F,
}

impl<F> S<F>
where
    F: std::future::Future,
{
    async fn do_thing(self) {
        (self.foo)(42).await;
    }
}

async fn example() {
    let s = S { foo };
    s.do_thing().await;
}

另请参见:

© www.soinside.com 2019 - 2024. All rights reserved.