我应该如何从代码的不同部分获得可写的静态对象?

问题描述 投票:0回答:1

我习惯了 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);

}

我能想到的选项是:

  1. 将所有写访问包装在不安全的 {} 中。我可以习惯 Rust 强迫你这样做的事实,并且每当我写入静态 mut 时都被迫仔细思考。但是,如果 static mut 确实将被删除或弃用,那么这甚至不是一个选项。
  2. 有几个人建议“依赖注入”,我认为这是一个奇特的术语,用于将对象传递给到处都需要它作为参数的函数。这不是一个现实的选择。

我还有什么其他选择?

rust static
1个回答
0
投票

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);
}
© www.soinside.com 2019 - 2024. All rights reserved.