如何在Rust中将异步函数放入地图中?

Uko*_* Ra 10 rust async-await

为编写异步路由器时,我无法处理异步功能hyper

这段代码:

use std::collections::HashMap;
use std::future::Future;

type BoxedResult<T> = Result<T, Box<dyn std::error::Error + Send + Sync>>;
type CalcFn = Box<dyn Fn(i32, i32) -> dyn Future<Output = BoxedResult<i32>>>;

async fn add(a: i32, b: i32) -> BoxedResult<i32> {
    Ok(a + b)
}

async fn sub(a: i32, b: i32) -> BoxedResult<i32> {
    Ok(a - b)
}

fn main() {
    let mut map: HashMap<&str, CalcFn> = Default::default();
    map.insert("add", Box::new(add));
    map.insert("sub", Box::new(sub));

    println!("map size: {}", map.len());
}
Run Code Online (Sandbox Code Playgroud)

生成以下编译器错误:

use std::collections::HashMap;
use std::future::Future;

type BoxedResult<T> = Result<T, Box<dyn std::error::Error + Send + Sync>>;
type CalcFn = Box<dyn Fn(i32, i32) -> dyn Future<Output = BoxedResult<i32>>>;

async fn add(a: i32, b: i32) -> BoxedResult<i32> {
    Ok(a + b)
}

async fn sub(a: i32, b: i32) -> BoxedResult<i32> {
    Ok(a - b)
}

fn main() {
    let mut map: HashMap<&str, CalcFn> = Default::default();
    map.insert("add", Box::new(add));
    map.insert("sub", Box::new(sub));

    println!("map size: {}", map.len());
}
Run Code Online (Sandbox Code Playgroud)

impl Future和之间似乎存在冲突dyn Future,但是我不知道如何处理。

Öme*_*den 5

发生这种情况是因为impl Future它是具体的唯一类型,dyn Future而是抽象类型。HashMap期望抽象类型,因为它只能容纳单个类型的实例。

如果我们可以对异步函数的返回类型进行装箱,则可以将这些期货添加到中HashMap

首先,我们需要更改以下类型CalcFn

type CalcFn = Box<dyn Fn(i32, i32) -> Pin<Box<dyn Future<Output = i32>>>>;
Run Code Online (Sandbox Code Playgroud)

然后可以做到这一点:

let mut map: HashMap<&str, CalcFn> = Default::default();
map.insert("add", Box::new(|a, b| Box::pin(add(a, b))));
map.insert("sub", Box::new(|a, b| Box::pin(sub(a, b))));

println!("map size: {}", map.len());

//map.get("add").unwrap()(2, 3).await
Run Code Online (Sandbox Code Playgroud)

这个完整的示例 简化FutureItem类型,使用i32的而不是一个Result。请也检查您的情况完整代码