取消引用 Rocket #[database] 连接是如何工作的?

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

我有以下代码:

#[database("pg_db")]
struct PgDbConn(diesel::PgConnection);

fn main() {
    rocket::ignite()
        .attach(PgDbConn::fairing())
        .mount("/", routes![find_one, find_all])
        .launch();
}

#[get("/<id>", format = "json")]
fn find_one(conn: PgDbConn, id: i32) -> Result<Json<Person>, NotFound<String>> {
    let one: QueryResult<Person> = person.find(id).first(&*conn);
    ...

我想知道我的

PgDbConn
结构如何最终成为一个连接。我的问题是关于 &*conn 中的 引用
解除引用
。有人可以详细解释一下这个机制吗?

rust dereference rust-diesel rust-rocket
1个回答
3
投票

我们来看看(部分)

database
属性宏的实现:

Ok(quote! {
    //...
    impl ::std::ops::Deref for #guard_type {
        type Target = #conn_type;

        #[inline(always)]
        fn deref(&self) -> &Self::Target {
            &self.0
        }
    }

    impl ::std::ops::DerefMut for #guard_type {
        #[inline(always)]
        fn deref_mut(&mut self) -> &mut Self::Target {
            &mut self.0
        }
    }
})
在您的示例中,

#guard_type
PgDbConn
#conn_type
diesel::PgConnection
,所以生成的代码如下所示:

impl ::std::ops::Deref for PgDbConn {
    type Target = diesel::PgConnection;

    #[inline(always)]
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl ::std::ops::DerefMut for PgDbConn {
    #[inline(always)]
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

使用

Deref
DerefMut
,您可以为自己的类型实现取消引用,在本例中为
PgDbConn
。现在,您可以编写
*conn
从您的
diesel::PgConnection
获取
PgDbConn
。但是,您需要 diesel::PgConnection
reference
。要获得引用,您必须再次引用取消引用的
PgDbConn
,因此最终结果是
&*conn

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