在 rust 中引用和取消引用数据库连接

Posted

技术标签:

【中文标题】在 rust 中引用和取消引用数据库连接【英文标题】:Referencing and dereferencing a db connection in rust 【发布时间】:2021-10-09 08:05:04 【问题描述】:

我的问题是关于 rust 中的取消引用引用

我有以下代码:

#[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); // Notice here deref & ref
    ...

我想知道我的PgDbConn 结构是如何作为连接结束的。有人可以详细解释一下机制吗?

【问题讨论】:

【参考方案1】:

让我们看看the implementation of the database attribute macro的(部分):

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_typediesel::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
    

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

【讨论】:

非常感谢您提供详细而相关的答案! 在火箭方面更好的解决方案是直接在#guard_type 上实现diesel::Connection,这样用户就不必进行&amp;*conn deref 转换。这似乎是一个很常见的混淆来源。为此,在他们的错误跟踪器中填写一个问题可能是有意义的。

以上是关于在 rust 中引用和取消引用数据库连接的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Rust 不在匹配模式中执行隐式取消引用强制?

当取消处理程序引用自身时,在 -dealloc 中取消 XPC 连接

Rust Deref与自动解引用

Redigo:尝试连接池时无效的内存地址或 nil 指针取消引用

取消引用的休眠 (JPA) 实体会发生啥情况?

sql golang查询时,无效的内存地址或nil指针取消引用。