我很好奇我的例子中&mut *transaction&mut transaction之间有什么区别,因为我一开始并不认为transaction是指针,但出于某种原因,&mut *transaction满足trait 约束,而&mut transaction则不满足trait 约束.

这是我的工作代码:

use sqlx::{PgPool, Transaction, Executor};
use chrono::{DateTime, Utc};

pub struct SimpleDbClient {
    db: PgPool,
}

pub trait AddCharacterEntries {
    async fn insert_character_entries(&self, timestamp: DateTime<Utc>, char_values: Vec<(char, i32)>) -> sqlx::Result<()>;
}

impl AddCharacterEntries for SimpleDbClient {
    async fn insert_character_entries(&self, timestamp: DateTime<Utc>, char_values: Vec<(char, i32)>) -> sqlx::Result<()> {
        let mut transaction = self.db.begin().await?;
        for (character, ascii_value) in char_values {
            sqlx::query!(
                r#"
                INSERT INTO character_log (timestamp, character, ascii_value)
                VALUES ($1, $2, $3)
                "#,
                timestamp,
                character as char,
                ascii_value
            )
            .execute(&mut *transaction)
            .await?;
        }
        transaction.commit().await?;
        Ok(())
    }
}

如果我将上面的更改为.execute(&mut transaction),我会得到这个错误:

rustc: the trait bound `&mut sqlx::Transaction<'_, sqlx::Postgres>: sqlx::Executor<'_>` is not satisfied
the following other types implement trait `sqlx::Executor<'c>`:
  <&'c mut sqlx::PgConnection as sqlx::Executor<'c>>
  <&'c mut sqlx::sqlx_postgres::PgListener as sqlx::Executor<'c>>
  <&'c mut sqlx::AnyConnection as sqlx::Executor<'c>>
  <&sqlx::Pool<DB> as sqlx::Executor<'p>> [E0277]
rustc: required by a bound introduced by this call [E0277]

这归结为进行某种类型的铸造吗?我很好奇这是否会被认为是一种限制,或者编译器认为这两个表达是不同的对象是否真的有意义.

推荐答案

我一开始就不认为transaction是一个指针

您缺少的是Transaction实现DerefDerefMut. 当您试图对实现Deref的值调用方法时,Rust可以通过这些特征自动反引用,但您也可以使用*操作符显式反引用. 然后&mut引用这个值,在本例中是PgConnection.

  • transactionTransaction<Postgres>类型.
  • *transactionPgConnection类型.
  • &mut *transaction&mut PgConnection类型.

由于xsx实现了这些特征,因此这允许您透明地在Transaction值上调用底层数据库连接的任何(非消费)方法,类似于您如何在Vec上透明地执行切片类型的任何(非消费)方法.

请注意,重新borrow (&*&mut *)是处理实现Deref(也许是DerefMut)的类型时的常见模式. 一些例子:

  • 给定some_vec就是Vec<T>&*some_vec就是&[T].
  • 给定some_box就是Box<T>&*some_box就是&T.

Rust相关问答推荐

使用windows crate Rust 展示windows

抽象RUST中的可变/不可变引用

如何在Tauri中将变量从后端传递到前端

如何格式化传入Rust中mysql crate的Pool::new的字符串

如何正确地将App handler传递给Tauri中的其他模块?

rust 蚀生命周期 不匹配-不一定超过此处定义的生命周期

什么时候使用FuturesOrdered?

如何执行数组文字的编译时串联?

tokio::spawn 有和没有异步块

将引用移动到线程中

如何基于常量在Rust中跳过一个测试

在 Bevy 项目中为 TextureAtlas 精灵实施 NearestNeighbor 的正确方法是什么?

Some(v) 和 Some(&v) 有什么区别?

`map` 调用在这里有什么用吗?

使用部分键从 Hashmap 中检索值

如何为返回正确类型的枚举实现 get 方法?

覆盖类型的要求到底是什么?为什么单个元素元组满足它?

C++ 中的 CRTP 是一种表达其他语言中特征和/或 ADT 的方法吗?

传递 Option<&mut T> 时何时需要 mut

在 Rust 中组合特征的不同方法是否等效?