具有多个泛型的 Axum 处理程序所需的类型注释

问题描述 投票:0回答:1

我正在尝试使用 2 个泛型 (

get_request
) 来路由处理程序 (
M: ApiTrait, C: ClientTrait
)

let mut app = Router::new();
app = app.route(
    "/model",
    get(get_request),
);


pub async fn get_request<M: ApiTrait, C: ClientTrait>(
    params: Query<RequestParams>,
    client_opt: Option<Extension<C>>,
    State(api): State<Arc<M>>,
) -> Result<Response, ApiError> { ... }

但出现错误:

error[E0283]: type annotations needed
   --> src/api/mod.rs:327:17
    |
327 |             get(get_request),
    |                 ^^^^^^^^^^^ cannot infer type of the type parameter `C` declared on the function `get_request`
    |
    = note: cannot satisfy `_: ClientTrait`
    = help: the following types implement trait `ClientTrait`:
              Client
              MockClient
note: required by a bound in `get_request`
   --> src/api/mod.rs:108:45
    |
108 | pub async fn get_request<M: ApiTrait, C: ClientTrait>(
    |                                          ^^^^^^^^^^^ required by this bound in `get_request`
help: consider specifying the generic arguments
    |
327 |             get(get_request::<S, C>),
    |                            ++++++++
```.

要解决此问题,我需要使用
指定其中一个泛型

get(get_request::<_, Client>)
而不是
get(get_request)
,尽管如此,我想保持它的灵活性,以便我可以在测试期间使用
MockClient

我有两个问题:

  1. 有什么方法可以保持两个仿制药的灵活性吗?
  2. 为什么 Axum handler 不能处理多个泛型?
rust rust-axum
1个回答
0
投票

这与泛型的数量无关,而是关于是否可以从调用上下文中推导出类型。

可以推导出

M
参数,因为
Router
与状态是强类型的。假设您有一个
.with_state()
或其他注释将路由器描述为
Router<Arc<MyState>>
,其中
M
将被推导为
MyState

C
参数无法推导,因为没有任何东西可以推导它。
Extension
未绑定到
Router
类型,因此无法从那里获取它。唯一的限制是
C: ClientTrait
;处理程序的
.route()
调用应该如何知道选择真实客户端或模拟客户端(或完全其他的东西)?

你真的没有任何选择;类型无法通过上下文推断出来,因此必须指定。


如果您有很多需要像这样的

ClientTrait
的处理程序,您可以将其所有功能包装起来,使用单个
C
泛型进行路由器设置,如下所示:

fn make_router<C: ClientTrait>() -> Router<Arc<MyState>> {
    let mut app = Router::new();
    app = app.route("/model", get(get_request::<_, C>));
    app
}

它仍然需要注释,但是通过“冒泡”,您只需为主要代码和测试代码指定一次

C
即可。

© www.soinside.com 2019 - 2024. All rights reserved.