rust error: lifetime may not live long enough

最初的写法与报错

关键报错信息:
error: lifetime may not live long enough
returning this value requires that 'life0 must outlive 'static
这是一个看起来很好解决的生命周期错误
其实也就是生命周期结合闭包和异步的问题

介绍:
为了实现失效缓存,写了一个包装redis操作的函数,在参数里接收闭包
但在使用的时候发现问题还是存在的
问题似乎与闭包和生命周期相关
于是按照错误输出的提示进行几次修改
并最终修改完成 不再报错

// 最初的代码片断
async fn delete_by_id(&self, id: &str) -> Result<(), MyErr> {
    // 这里是要失效的redisKey 可能不止一个所以使用vec
    let cache_keys = vec![];
    // 调用redis包装方法 传入redis连接 和业务逻辑闭包
    redisutil::cache_wrap::invalid_cache_keys(self.redis.clone(), cache_keys, || Box::pin(async move {
        // 业务逻辑处理代码 调用关系数据库封装方法完成删除动作
        let res = Dao::delete_by_id(&self.db.clone(), id).await?;
        Ok(res)
    })).await
}

由报错信息推断是闭包捕获了self的引用
而引起生命周期问题
&self的生命必须和’static一样长或长与’static
这是不可能的事 肯定是那里有问题

error: lifetime may not live long enough
  --> service\maitian\user\src\svc.rs:38:13
   |
35 |       async fn delete_by_id(&self, id: &str) -> Result<(), MyErr> {
   |                             - lifetime `'life0` defined here
...
38 | /             Box::pin(async move {
39 | |                 let res = Dao::delete_by_id(&self.db.clone(), id).await?;
40 | |                 Ok(res)
41 | |             })
   | |______________^ returning this value requires that `'life0` must outlive `'static`

第一次修改 改成这样之后报不能移动的错误

把db和id单独拉出来试试

async fn delete_by_id(&self, id: &str) -> Result<(), MyErr> {
    let cache_keys = vec![];
    let db = self.db.clone(); // 单独拉出来的db
    let id = id.to_owned(); // 单独拉出来的id
    redisutil::cache_wrap::invalid_cache_keys(self.redis.clone(), cache_keys, ||  Box::pin(async move {
            let res = Dao::delete_by_id(&db, &*id).await?;
            Ok(res)
        })).await
}

报错信息变了
db存活的时间不够长
闭包只捕获了db的引用
db本身并没有转移到闭包里

error[E0507]: cannot move out of `db`, a captured variable in an `Fn` closure
  --> service\maitian\user\src\svc.rs:41:22
   |
37 |           let db = self.db.clone();
   |               -- captured outer variable
38 |           let id = id.to_owned();
39 |           redisutil::cache_wrap::invalid_cache_keys(self.redis.clone(), cache_keys, || {
   |                                                                                     -- captured by this `Fn` closure
40 |
41 |               Box::pin(async move {
   |  ______________________^
42 | |                 let res = Dao::delete_by_id(&db, &*id).await?;
   | |                                              --
   | |                                              |
   | |                                              variable moved due to use in generator
   | |                                              move occurs because `db` has type `sqlx::Pool<MySql>`, which does not implement the `Copy` trait
43 | |                 Ok(res)
44 | |             })
   | |_____________^ `db` is moved here

第二次修改

似乎修改的方向是对的 self不报错了 只有id报错
现在只剩下id的问题了

async fn delete_by_id(&self, id: &str) -> Result<(), MyErr> {
    let cache_keys = vec![];
    redisutil::cache_wrap::invalid_cache_keys(self.redis.clone(), cache_keys, || {
        // 在还没有进入异步的地方把db克隆出来
        // 最终返回的future不再引用self
        let db = self.db.clone();
        // 返回future
        Box::pin(async move {
            let res = Dao::delete_by_id(&db, id).await?;
            Ok(res)
        })
    }).await
}
error: lifetime may not live long enough
  --> service\maitian\user\src\svc.rs:39:13
   |
35 |       async fn delete_by_id(&self, id: &str) -> Result<(), MyErr> {
   |                                        - lifetime `'life1` defined here
...
39 | /             Box::pin(async move {
40 | |                 let res = Dao::delete_by_id(&db, id).await?;
41 | |                 Ok(res)
42 | |             })
   | |______________^ returning this value requires that `'life1` must outlive `'static`

最后 没有错误的写法 正确的改法

async fn delete_by_id(&self, id: &str) -> Result<(), MyErr> {
    let cache_keys = vec![];
    redisutil::cache_wrap::invalid_cache_keys(self.redis.clone(), cache_keys, || {
        let db = self.db.clone(); // db
        let id = id.to_owned();  // id
        // db与id保留在当前闭包里 
        // 最终返回的future里不再引用self
        Box::pin(async move {
            Ok(Dao::delete_by_id(&db, &*id).await?)
        })
    }).await
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独杆小蓬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值