Rust:避坑篇:坑爹的 "*"

在 Rust 项目中使用 crate = "*" 作为 Cargo.toml 文件中的依赖项声明是一种指定依赖关系的方式,意图告诉 Cargo 包管理器自动选择 crate 库的最新版本。这种做法看似简便,但实际上可能带来一些风险和复杂性,特别是在项目依赖管理和版本兼容性方面。

在今天以前,我都认为这是一个好用且实用的写法,因为它可以始终选择最新版本,并且在我的工作中广泛使用,但是!在今天我彻底的改变了我的想法,并直接抛弃了这种习惯。并打算永不用"*"为什么?请往下看

报错,版本不对:

今天开心的写着业务,写到用bb8创建redis连接池:

rust 复制代码
use crate::config::CFG;
use bb8::Pool;
use bb8_redis::{bb8, RedisConnectionManager};
use tokio::sync::OnceCell;
pub static REDIS: OnceCell<Pool<RedisConnectionManager>> = OnceCell::const_new();

pub async fn init_redis_pool() {
    let manager = RedisConnectionManager::new(CFG.redis.redis_url.clone()).unwrap();

    let pool = Pool::builder()
        .build(manager)
        .await
        .expect("db connect failed");

    REDIS.get_or_init(|| async { pool }).await;
}

然后运行项目,报错!

bush 复制代码
thread 'main' panicked at /home/pomelo/.cargo/registry/src/mirrors.ustc.edu.cn-
12df342d903acd47/tokio-0.3.7/src/time/driver/handle.rs:50:18: 
there is no timer running, must be called from the context of a Tokio 0.3.x runtime note: run 
with `RUST_BACKTRACE=1` environment variable to display a backtrace

嗯?

tokio-0.3.7?这什么东西,谁给我从清朝墓里刨出来的?

版本不对,那就检查下吧toml文件吧。

toml 复制代码
tokio = { version = "1", features = ["full"] }
bb8 = "*" 

我tokio异步运行时版本没错呀? bb8也是最新的呀? 0.3.7是哪儿来的?

难道bb8最新版本这么low?不应该啊,前两天还在更新这个库,怎么可能异步运行时版本这么低?不放心的我还是去docs.rs查了一下,

bb8最新版本0.8.1,又去github上面看了下源码:作者也在用tokio 1的版本呀?那说明运行时没问题,那为什么我的不支持呢?

除非我的bb8不是最新版本0.8.1

得,看看我的什么版本直接去cargo.lock文件里看一下不就行了

lock 复制代码
 
[[package]] 
name = "bb8" 
version = "0.6.2" 
source = "registry+https://github.com/rust-lang/crates.io-index" 
checksum = "486f2c0824c803d4e77f7cb915c9f0413a772f1dcef3ccf304bd39fa099c781a" 
dependencies = [ 
"async-trait", 
"futures-channel", 
"futures-util", 
"parking_lot 0.11.2", 
"tokio 0.3.7", 
]

还真是这样,那这更不对了,我明明用的最新版本,怎么成了0.6.2了?不对,这个"*" 有问题

坑爹的"*"

我又去查了下"*"

Cargo.toml 文件中使用 bb8 = "*" 时,理论上 Cargo 应该解析并使用最新的 bb8 版本。然而,如果项目中存在其他依赖项,它们可能会间接地引入 bb8 的一个较旧版本,或者项目可能有某些限制,导致 Cargo 无法使用最新版本。这种情况下,Cargo 会尝试找到一个满足所有依赖项版本要求的解决方案,有时这可能是一个较旧的版本。

  • 不兼容的风险:自动选择最新版本可能导致不兼容的问题。新版本可能引入了破坏性变更(breaking changes),这可能会影响项目。
  • 依赖项的间接影响 :如果项目中其他依赖项也依赖于 bb8(直接或间接),它们可能指定了不同的版本要求,这可能导致 Cargo 解析为较旧的 bb8 版本,而不是最新的。

也就是说

在我的项目中,虽然指定了 bb8 = "*",意在使用最新版的 bb8,但 Cargo 实际上解析并使用了版本 0.6.2。这是因为的项目或其它依赖项存在某些限制或要求,导致 Cargo 无法使用 bb8 的最新版本。特别是在项目中使用了 Tokio 1.x 版本的情况下,bb8 0.6.2 版本依赖于不兼容的旧版 Tokio(0.3.7),导致了版本冲突和运行时错误。

明白以后,建议和最佳实践

  • 明确指定版本 :尽量指定依赖项的具体版本号(例如 bb8 = "0.7.0"),这可以提高项目的稳定性和可预测性。
  • 定期更新依赖:定期检查和更新依赖项,确保使用的是支持和兼容的版本。
  • 避免使用"*" :避免使用 * 来指定依赖项版本,因为这可能导致意外的版本冲突和不兼容问题。
  • 依赖管理工具 :使用依赖管理工具(如 cargo-outdatedcargo-tree)来帮助识别和管理依赖关系。

所以,再也不会用"*"了.坑爹!from刘金,转载请注明原文链接。感谢!

相关推荐
来自旧金山的勇士20 分钟前
WSL->Ubunut安装Redis
后端
大葱白菜22 分钟前
Java Set 集合详解:从基础语法到实战应用,彻底掌握去重与唯一性集合
java·后端
大葱白菜23 分钟前
Java Map 集合详解:从基础语法到实战应用,彻底掌握键值对数据结构
java·后端
小猪乔治爱打球29 分钟前
[Golang修仙之路] 算法专题:回溯(递归)
后端·面试
昵称为空C37 分钟前
SpringBoot数据存储时区选择,符合国际化和特定时区方案
spring boot·后端
ldj20202 小时前
SpringBoot为什么使用new RuntimeException() 来获取调用栈?
java·spring boot·后端
超龄超能程序猿2 小时前
Spring 应用中 Swagger 2.0 迁移 OpenAPI 3.0 详解:配置、注解与实践
java·spring boot·后端·spring·spring cloud
江南一点雨2 小时前
Tokenizer 和 BPE
后端
风象南2 小时前
SpringBoot配置属性热更新的轻量级实现
java·spring boot·后端
洛阳泰山2 小时前
Spring Boot 整合 Nacos 实战教程:服务注册发现与配置中心详解
java·spring boot·后端·nacos