在前文中我们分析了使用lazy_static来构造全局变量,典型用法如下:
#[macro_use]
extern crate lazy_static;
use std::collections::HashMap;
lazy_static! {
static ref VEC:Vec<u8> = vec![0x19u8, 0x21u8];
static ref MAP: HashMap<u32, String> = {
let mut map = HashMap::new();
map.insert(2021, "year".to_owned());
map
};
static ref PAGE:u32 = init_val(2018);
}
fn init_val(i: u32) -> u32 {
i * 2
}
fn main() {
println!("{:?}", *PAGE);
println!("{:?}", *VEC);
println!("{:?}", *MAP);
}
once_cell 提供了 unsync::OnceCell 和 sync::OnceCell 这两种接口,前者用于单线程,后者用于多线程,可用来存储堆上的信息,并且具有最多只能赋值一次的特性。
提供的API如下:
fn set(&self, value: T) -> Result<(), T> { ... }
=> 安全的设置全局变量
fn get(&self) -> Option<&T> { ... }
=> 获取已经设置的全局变量
get_or_init(Fn)
=> 获取全局变量,为空则初始化
Lazy::new(Fn)
=> 延迟创建全局变量
典型用法如下:
use std::{sync::Mutex, collections::HashMap};
use once_cell::sync::Lazy;
use once_cell::sync::OnceCell;
static GLOBAL_DATA: Lazy<Mutex<HashMap<i32, String>>> = Lazy::new(|| {
let mut m = HashMap::new();
m.insert(13, "chain".to_string());
m.insert(74, "queue".to_string());
Mutex::new(m)
});
fn global_data() -> &'static Mutex<HashMap<i32, String>> {
static INSTANCE: OnceCell<Mutex<HashMap<i32, String>>> = OnceCell::new();
INSTANCE.get_or_init(|| {
let mut m = HashMap::new();
m.insert(13, "sky".to_string());
m.insert(74, "walker".to_string());
Mutex::new(m)
})
}
相比而言,once_cell没有采用宏的方式实现,代码看起来更加干净易懂。
网友评论