我正在尝试使用 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
。这与泛型的数量无关,而是关于是否可以从调用上下文中推导出类型。
可以推导出
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
即可。