Rust 用 once_cell 管理全局配置与单例连接:初始化只跑一次
test12026-10-224 次阅读
为什么不用 lazy_static
lazy_static 靠宏生成静态变量,类型推导和 IDE 支持都一般。once_cell 提供 Lazy 与 OnceCell,用普通 API 表达一次性初始化,编译报错更友好,也是标准库 once_cell 提案的雏形。
用 Lazy 初始化配置
进程级、启动即确定的全局对象(如配置、日志句柄)适合用 Lazy,第一次访问时才初始化,且只初始化一次。
use once_cell::sync::Lazy;
use std::collections::HashMap;
static CONFIG: Lazy<HashMap<String, String>> = Lazy::new(|| {
let mut m = HashMap::new();
m.insert("env".into(), std::env::var("APP_ENV").unwrap_or_else(|_| "dev".into()));
m.insert("region".into(), "cn-hangzhou".into());
m
});
fn main() {
println!("env = {}", CONFIG.get("env").unwrap());
}用 OnceCell 做一次性的运行时初始化
配置来自外部、不能在编译期确定的对象(比如连接池),用 OnceCell 在运行时第一个请求到来时初始化,后续直接复用,避免每次都建连。
use once_cell::sync::OnceCell;
use std::sync::Mutex;
struct DbPool {
conns: usize,
}
static POOL: OnceCell<Mutex<DbPool>> = OnceCell::new();
fn pool() -> &'static Mutex<DbPool> {
POOL.get_or_init(|| {
// 真实场景里在这里建连接池,只跑一次
Mutex::new(DbPool { conns: 8 })
})
}
fn query() -> usize {
let g = pool().lock().unwrap();
g.conns
}关键结论
- Lazy 适合启动期确定的全局值,OnceCell 适合运行时一次性初始化。
- 两者都保证初始化只发生一次,且是线程安全的。
- 比 lazy_static 更贴近未来的标准库写法,类型提示更清晰。
T
test1
文章作者
为什么不用 lazy_static lazy_static 靠宏生成静态变量,类型推导和 IDE 支持都一般。once_...
- 分类
- 技术
- 发布时间
- 2026-10-22
- 字数
- 约 1156 字
- 阅读
- 4 次
