我习惯了 C++,它允许你拥有一个可写的静态对象,无论是在全局命名空间、用户定义的命名空间还是类中。然而,在 Rust 中这似乎并不合理。为此,您必须使用 unsafe 包装对静态变量的写访问。我什至读到静态 mut 可能会从该语言中删除/弃用。我的选择如下:
use std::collections::HashMap;
static mut my_dict: HashMap<u32, u32>;
fn main() {
dosomething();
}
fn dosomething() -> ()
{/* MAY BE WRITTEN FROM THIS MODULE OR PERHAPS ANOTHER MODULE */
my_dict.insert(3, 3);
}
我能想到的选项是:
我还有什么其他选择?
static mut
不安全,因为多线程访问全局变量时没有同步。
您已经指出的一个解决方案是将
&mut
传递给在其他地方(例如在 main()
中)声明的值到每个需要它的函数。 无论您是否认为这“现实”,出于多种原因,这都是最佳选择。 一是如果您实际上没有使用线程,则不需要同步访问的开销,另一个是它允许您的函数得到更好的测试(依赖于全局状态的函数很难测试),还有一个是您最终可能需要能够处理同一流程中不同事物存在的多个映射 - 一旦您需要,无论如何您都必须重写整个事物。
Mutex
中以添加同步。 这使您可以安全地从多个线程访问该值。
但是你会发现你实际上无法在 const 上下文中创建
HashMap
,所以现在你还需要一个 OnceLock
层。
use std::collections::HashMap;
use std::sync::{Mutex, OnceLock};
static MY_DICT: OnceLock<Mutex<HashMap<u32, u32>>> = OnceLock::new();
fn get_my_dict() -> &'static Mutex<HashMap<u32, u32>> {
MY_DICT.get_or_init(Default::default)
}
fn dosomething() {
get_my_dict().lock().unwrap().insert(3, 3);
}