在 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
现在我的问题是:
- 我该如何解决这个问题才能使匹配正常进行?
- 是否有更好的方法可以根据用户 CLI 标志在 actix 上以编程方式设置默认服务器行为?对于上下文,这或多或少是我所拥有的:
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,
}
};
现在,您只需匹配一个整数,而不是每次调用都进行额外的分配和动态分派。
我有一个变量可以控制哪个函数是我的网络应用程序的默认行为,但是这两个函数都是 async
并且它不会让我这样做,因为它们是不同的闭包。像这样的东西会重现同样的错误:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=db0269ef4852a94438e6d4925ca83d3b
现在我的问题是:
- 我该如何解决这个问题才能使匹配正常进行?
- 是否有更好的方法可以根据用户 CLI 标志在 actix 上以编程方式设置默认服务器行为?对于上下文,这或多或少是我所拥有的:
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,
}
};
现在,您只需匹配一个整数,而不是每次调用都进行额外的分配和动态分派。