Dje*_*ent 8 types rust actix-web
我想在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."),
}
}
Run Code Online (Sandbox Code Playgroud)
我在如下视图中使用它:
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)
}
Run Code Online (Sandbox Code Playgroud)
如果视图与上面的一样简单,则一切正常,但如果视图稍微复杂一点,我就会遇到问题:
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)
}
Run Code Online (Sandbox Code Playgroud)
我得到的错误:
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`
Run Code Online (Sandbox Code Playgroud)
我尝试将 提取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
Run Code Online (Sandbox Code Playgroud)
我真的不明白为什么会发生以及如何解决它。
当函数返回类似 的内容时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)
}
Run Code Online (Sandbox Code Playgroud)
它看到最后的语句返回一个 opaque impl Responder,而早期的return语句返回一个crete HttpResponse。即使您知道它们实际上是同一类型,但这只是因为您碰巧知道如何render_response实现。这很好,因为它可以防止代码中不相关部分的更改破坏此函数:您不希望对主体的更改render_response导致.login
将 的返回类型更改render_response为具体类型,它将起作用:
fn render_response(
tera: web::Data<Tera>,
template_name: &str,
context: &Context,
) -> HttpResponse;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6892 次 |
| 最近记录: |