我想为在actix中呈现模板创建一个辅助函数,如下所示:
fn render_response(
tera: web::Data<Tera>,
template_name: &str,
context: &Context,
) -> impl Responder {
match tera.render(template_name, context) {
Ok(rendered) => HttpResponse::Ok().body(rendered),
Err(_) => HttpResponse::InternalServerError().body("Failed to resolve the template."),
}
}
我在下面的视图中使用它:
async fn signup(tera: web::Data<Tera>) -> impl Responder {
let mut data = Context::new();
data.insert("title", "Sign Up");
render_response(tera, "signup.html", &data)
}
如果视图和上面的视图一样简单,那么一切都可以正常工作,但是如果视图稍微复杂一些,我就会遇到一个问题:
async fn login(tera: web::Data<Tera>, id: Identity) -> impl Responder {
let mut data = Context::new();
data.insert("title", "Login");
if let Some(id) = id.identity() {
return HttpResponse::Ok().body(format!("Already logged in: {}.", id));
}
render_response(tera, "login.html", &data)
}
我所犯的错误:
error[E0308]: mismatched types
--> src\main.rs:101:5
|
42 | ) -> impl Responder {
| -------------- the found opaque type
...
101 | render_response(tera, "login.html", &data)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `actix_web::HttpResponse`, found opaque type
|
= note: expected type `actix_web::HttpResponse`
found opaque type `impl actix_web::Responder`
我尝试将return HttpResponse...
提取到一个也返回impl Responder
的单独函数中,但我现在得到了不同的错误:
error[E0308]: mismatched types
--> src\main.rs:101:5
|
42 | ) -> impl Responder {
| -------------- the found opaque type
...
101 | render_response(tera, "login.html", &data)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
|
= note: expected type `impl actix_web::Responder` (opaque type at <src\main.rs:104:28>)
found opaque type `impl actix_web::Responder` (opaque type at <src\main.rs:42:6>)
= note: distinct uses of `impl Trait` result in different opaque types
我真的不明白为什么会发生这种事,也不明白如何解决。
发布于 2020-11-05 03:27:36
当函数返回类似impl Responder
的内容时,意味着它返回实现Responder
的某种类型。编译器可以推断类型,但是对任何调用者来说它都是“不透明的”,这意味着您不能假设类型实际上是什么。即使编译器有更多的信息,类型总是在函数边界上匹配的。这一点很重要,这样人类就可以在函数级别对代码进行推理,而不必将有关程序的各个行的所有信息保存在他们的头脑中。
函数还必须只返回一种类型,所以当编译器遇到这样的函数时:
async fn login(tera: web::Data<Tera>, id: Identity) -> impl Responder {
let mut data = Context::new();
data.insert("title", "Login");
if let Some(id) = id.identity() {
return HttpResponse::Ok().body(format!("Already logged in: {}.", id));
}
render_response(tera, "login.html", &data)
}
它看到返回不透明impl Responder
的最后一条语句和返回具体HttpResponse
的早期return
语句。即使您知道它们实际上是相同的类型,这只是因为您碰巧知道render_response
是如何实现的。这很好,因为它可以防止代码中不相关部分的更改破坏此函数:您不希望对render_response
主体的更改导致login
中的类型不匹配。
将render_response
的返回类型更改为具体类型,它将工作:
fn render_response(
tera: web::Data<Tera>,
template_name: &str,
context: &Context,
) -> HttpResponse;
https://stackoverflow.com/questions/64693182
复制相似问题