提供了和这两种Cell(字面意思,前者用于单线程,后者用于多线程),用来存储堆上的信息,并且具有最多只能赋值一次的特性。API大概是:
impl OnceCell {
fnnew() -> OnceCell { ... }
fnset(&self, value: T) ->Result { ... }
fnget(&self) ->Option { ... }
}
用法
安全的初始化全局变量
usestd::;
useonce_cell::sync::OnceCell;
#[derive(Debug)]
pubstructLogger{
// ...
}
staticINSTANCE: OnceCell = OnceCell::new();
implLogger {
pubfnglobal() -> &'staticLogger {
INSTANCE.get().expect("logger is not initialized")
}
fnfrom_cli(args: env::Args) ->Result {
// ...
}
}
fnmain() {
letlogger = Logger::from_cli(env::args()).unwrap();
INSTANCE.set(logger).unwrap();
// 之后就统一使用`Logger::global()`
}
Lazy产生全局变量
包中提供了,(也分sync和unsync版)可以起到类似之前提到过的lazy_static的作用——在第一次使用的时候产生一个动态的全局静态变量
usestd::;
useonce_cell::sync::Lazy;
staticGLOBAL_DATA: Lazy = Lazy::new(|| {
letmutm = HashMap::new();
m.insert(13,"Spica".to_string());
m.insert(74,"Hoyten".to_string());
Mutex::new(m)
});
fnmain() {
println!("{:?}", GLOBAL_DATA.lock().unwrap());
}
其中的好处就是不需要神奇的宏魔法了,这也是近期使用它取代了之前的的原因:https://github.com/tokio-rs/tokio/pull/3187
比起,我们还支持局部变量
useonce_cell::unsync::Lazy;
fnmain() {
letctx =vec![1,2,3];
letthunk = Lazy::new(|| {
ctx.iter().sum::()
});
assert_eq!(*thunk,6);
}
而且使用OnceCell还可以嵌入到结构体中
因此可以用它来构建其它更复杂的东西!
小结
那大家可能好奇它和究竟有什么区别。小结一下就是:
就像上边的例子展现的,更灵活易用,也没用宏魔法
可以支持no_std
不过往上游提交pr也有很长时间了,有兴趣的可以去围观下https://github.com/rust-lang/rfcs/pull/2788
领取专属 10元无门槛券
私享最新 技术干货