我有以下代码:
#[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
中的 引用 和 解除引用。有人可以详细解释一下这个机制吗?
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
。