我有一个内部使用 hyper 的库。我希望用户能够创建一个 App
,其中包含一个内部处理 HTTP 连接的 Server
。
use hyper::server::conn::AddrIncoming;
use hyper::server::Server;
use hyper::service::service_fn_ok;
use std::net::SocketAddr;
pub struct App {
inner: Server<AddrIncoming, ()>,
}
impl App {
pub fn new() -> Self {
let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
let inner = Server::bind(&addr).serve(|| service_fn_ok(|_req| unimplemented!()));
App { inner }
}
}
( Playground link )
如预期的那样,错误是:
error[E0308]: mismatched types
--> src/lib.rs:15:15
|
15 | App { inner }
| ^^^^^ expected (), found closure
|
= note: expected type `hyper::server::Server<_, ()>`
found type `hyper::server::Server<_, [closure@src/lib.rs:13:47: 13:88]>`
没有很好的记录,但是 Server
的第二个类型参数是它使用的 MakeService
的类型。
我不知道如何引用inner
类型的闭包。有什么方法可以将闭包装箱以编译代码吗?有没有一种方法可以手动实现 MakeService
,而不是使用闭包?
hyper docs 引用函数make_service_fn
,它返回一个MakeServiceFn
,但是类型不是public,所以我不能在类型中使用它内部
。
最佳答案
问题是由于类型不匹配。在 Rust 中,类型参数是结构类型的一部分,因此结构中服务器的类型参数必须与您在结构中定义的类型参数匹配。在你的情况下,他们没有。
您的问题有 2 个解决方案。
将第二个服务器参数的类型参数添加到您的结构
pub struct App<T> {
inner: Server<AddrIncoming, T>,
}
现在您将能够为服务器的第二个类型参数创建具有不同类型的应用
找到您正在创建的服务器的第二个参数的类型
在你的例子中,第二个参数的类型是``,所以你可以这样声明你的结构:
type Service = ?; // This is really hard to find in this case.
pub struct App {
inner: Server<AddrIncoming, Service>,
}
结论
在你的情况下,我会推荐第一个,因为 Server
的第二个类型参数的类型很难找到,并且很可能在你的程序开发过程中发生变化,所以它更容易在你的结构上只有一个类型参数。
然而,如果您不知道其类型参数未实现某些特征,有时您将无法在您的服务器上使用某些方法,因此您可以将这些特征添加到您的类型参数中,如下所示:
pub struct App<T: Service> {
inner: Server<AddrIncoming, T>,
}
建议不要将类型参数放在结构本身上,而只将它们放在 impl
block 上:
pub struct App<T> {
inner: Server<AddrIncoming, T>,
}
impl App<T: Service> {
// Here you'll be able to use the method from Server where T has to be a Service.
}
你也可以对这样的函数做同样的事情:
pub struct App<T> {
inner: Server<AddrIncoming, T>,
}
fn some_function(app: App<T: Service>) {
// Here you'll be able to use the method from Server where T has to be a Service
}
关于rust - 如何将 hyper::server::Server 存储为结构中的字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56469502/