在 Rust 中的两个异步函数之间进行选择的变量 - 不兼容的手臂类型

Variable that chooses between two async functions in rust - incompatible arm types

我有一个变量可以控制哪个函数是我的网络应用程序的默认行为,但是这两个函数都是 async 并且它不会让我这样做,因为它们是不同的闭包。像这样的东西会重现同样的错误: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=db0269ef4852a94438e6d4925ca83d3b

现在我的问题是:

main.rs

// Matches comes from the command line
let a = match matches.occurrences_of("default"){
        1 => handlers::forward,
        _ => handlers::resource_not_found,
    };

... setting up db, auth etc

HttpServer::new(move || {
            App::new()
            ... lots of routes 
            .default_service(web::route().to(a))

handlers.rs


pub async fn resource_not_found(
) -> Result<HttpResponse, Error> {
   Ok(HttpResponse::NotFound().body("Resource does not exist"))
}
pub async fn forward(
) -> Result<HttpResponse, Error> {
   Ok(HttpResponse::Ok().body("Resource does exist"))
}

How do I solve this so that the match works

您可以创建两个闭包,它们都是 return 盒装未来,并将它们强制为函数指针:

use std::pin::Pin;
use std::future::Future;

let a: fn() -> Pin<Box<dyn Future<Output = Result<HttpResponse, Error>>>> =
    match matches.occurrences_of("default") {
        1 => || Box::pin(handlers::forward()),
        _ => || Box::pin(handlers::resource_not_found()),
    };

如果功能真的那么简单,那么就可以避免装箱和return std::future::Ready:

use std::pin::Pin;
use std::future::{Future, Ready, ready};

let a: fn() -> Ready<Result<HttpResponse, Error>> =
    match matches.occurrences_of("default") {
        1 => || handlers::forward,
        _ => || handlers::resource_not_found,
    };

// handlers.rs

pub fn resource_not_found(
) -> Ready<Result<HttpResponse, Error>> {
   ready(Ok(HttpResponse::NotFound().body("Resource does not exist")))
}

pub fn forward(
) -> Ready<Result<HttpResponse, Error>> {
   ready(Ok(HttpResponse::Ok().body("Resource does exist")))
}

Is there a better way to set default server behavior programmatically on actix based on user CLI flags

您可以在 内部 新处理程序而不是外部进行匹配:

let x = matches.occurrences_of("default");
let a = move || async move {
    match x {
        1 => handlers::forward().await,
        _ => handlers::resource_not_found().await,
    }
};

现在,您只需匹配一个整数,而不是每次调用都进行额外的分配和动态分派。