首页 文章

“trait core :: ops :: Fn <(Request,Response)>未实现”对于将连接池传递给Hyper处理程序时的闭包

提问于
浏览
1

我正在尝试使用Hyperr2d2在Rust中构建一个小型Web服务,但是我无法解析编译器抛出的错误消息,所以我希望有人可以帮助我 .

请考虑以下代码:

extern crate hyper;
extern crate postgres;
extern crate r2d2;
extern crate r2d2_postgres;

use hyper::Server;
use hyper::server::{Request,Response,Handler};
use r2d2_postgres::{SslMode, PostgresConnectionManager};
use r2d2::{Pool, PooledConnection};
use postgres::{Connection};

fn connect() -> Pool<PostgresConnectionManager>{
    let config = r2d2::Config::default();
    let conns = "postgres://abc:abc@localhost/abc";
    let manager = PostgresConnectionManager::new(conns, SslMode::None).unwrap();
    let pool = r2d2::Pool::new(config, manager).unwrap();
    return pool;
}

fn hello(pool: Pool<PostgresConnectionManager>, req: Request, res: Response) {
    res.send(b"Hello world").unwrap();
}

fn main() {
    let pool = connect();
    let dispatch = move |req: Request, res: Response| hello(pool, req, res);
    Server::http("127.0.0.1:3000").unwrap().handle(dispatch).unwrap();
}

我的目标是在函数 hello 中使用 pool . 通过使用闭包,我想,我可以通过一个环境变量wile仍然符合Hyper的期望 . 不幸的是,我收到以下错误:

src/main.rs:28:45: 28:61 error: the trait `for<'r, 'r, 'r> core::ops::Fn<(hyper::server::request::Request<'r, 'r>, hyper::server::response::Response<'r>)>` is not implemented for the type `[closure@src/main.rs:27:20: 27:76 pool:r2d2::Pool<r2d2_postgres::PostgresConnectionManager>]` [E0277]
src/main.rs:28     Server::http("127.0.0.1:3000").unwrap().handle(dispatch).unwrap();
                                                           ^~~~~~~~~~~~~~~~
src/main.rs:28:45: 28:61 help: run `rustc --explain E0277` to see a detailed explanation
error: aborting due to previous error

这取决于 pool 的类型 . 如果我试图传递一个 i64 ,那么's all swell and the compiler doesn'抱怨 .

1 回答

  • 1

    如果我们查看hyper的源代码,我们可以看到实现所需特征的闭包:

    impl<F> Handler for F where F: Fn(Request, Response<Fresh>), F: Sync + Send {
        fn handle<'a, 'k>(&'a self, req: Request<'a, 'k>, res: Response<'a, Fresh>) {
            self(req, res)
        }
    }
    

    这意味着您的闭包需要实现 Fn(Request, Response) + Sync + Send ,以便为您实现 Handler 特征 . 否则,您需要自己实现它 . 由于您的闭包按值获取 pool ,它只实现 FnOnce(Request, Response) (只能在 pool 移入函数时调用一次) .

    要解决此问题,请对池进行不可变引用,以便可以多次调用函数(即实现 Fn(Request, Response) ) .

    fn hello(pool: &Pool<PostgresConnectionManager>, req: Request, res: Response) {
        res.send(b"Hello world").unwrap();
    }
    
    fn main() {
        let pool = connect();
        let dispatch = move |req: Request, res: Response| hello(&pool, req, res);
        Server::http("127.0.0.1:3000").unwrap().handle(dispatch).unwrap();
    }
    

    注:特征 Fn(Request, Response) 是较高等级特征的语法糖 for<'r> Fn(Request<'r,'r>, Response<'r>) . 这是因为 RequestResponse 在生命周期中都是通用的,因此您的函数必须处理任何生命周期的 RequestResponse .

相关问题