跨多个模块访问单例[重复]

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了跨多个模块访问单例[重复]相关的知识,希望对你有一定的参考价值。

我正在尝试使用lazy_static包来创建单例并在不同的模块中使用它。这是可能的,甚至是推荐的吗?我还在学习如何构建Rust程序,并且每个文件都是自己的模块。

我在main.rs中有以下内容,我可以访问它的值

lazy_static! {
    static ref GAMEDATA: gamedata::data::GameDataS =
        gamedata::data::load_data("./src/assets/data.json".to_string());
}

fn main() {
    println!("data{}", GAMEDATA.width);
}

当我试图在不同的模块中访问GAMEDATA时,我得到了

在此范围内未找到

例如,在一个名为game的模块中

pub struct Game {}
impl Game {
    println!("data{}", GAMEDATA.width);
}

是否有可能在所有模块中创建一个全局变量?还有其他方法我应该考虑一下吗?也许不经常使用模块?

答案

如果你的静态变量在另一个非父模块中,你的问题似乎是在pub之前缺少static修饰符。另外,正如其他人所指出的,使用变量(impl块)的代码不是有效的Rust语法。

除此之外,您还需要使用use(例如use GAMEDATA;)导入静态变量,请参阅Quan Brew's answer

但是,我想讨论在Rust中使用静态和单例模式。

Static variables in Rust

在Rust中,我们通常避免使用静态变量在大多数情况下,他们可以通过const替换为适当的常数。因为静态变量可以在线程之间共享,所以具有外部可变性的是Rust中的unsafe。这就是为什么你不能使用lazy_static进行外部可变性的原因。

虽然具有外部可变性的静态确实有它们的用途,但它们是特定的,应该是合理的,否则就应该避免。如this section of the Rust Book中所描述的内部可变性甚至不允许在线程之间共享。

Singleton Pattern in Rust

我不认为使用静态来获得单例模式是个好主意。这种模式在Rust中并不常见。我们通常将所有可变的东西作为参数传递。

Solutions if you need immutable data

  1. const使它成为一个常数。
  2. 如果数据太多,请使用static
  3. 如果需要非常量初始化,可以保持lazy_static。

Solutions if you need to mutate data

  1. 把你的单身人士放入Mutex或其他锁。这将确保正确的并发访问。
  2. 使用thread_local macro + inner mutability with RefCell使其成为局部线程
  3. 放弃“单身模式”的想法,并通过参数传递结构(推荐)。
另一答案

您需要useGAMEDATA导入当前范围,如modules section in the book中所述。

示例代码(playground):

#[macro_use]
extern crate lazy_static; // 1.1.0

lazy_static! {
    static ref GAMEDATA: String = "hello".to_string();
}

mod foo {
    use GAMEDATA;
    pub fn bar() {
        println!("{}", *GAMEDATA);
    }
}

fn main() {
    foo::bar();
}

但是,Rust中不建议使用单例模式。对于初学者来说,在学习阶段,你最好避免单身。 (见bzim's answer

以上是关于跨多个模块访问单例[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何跨多个命名空间C#定义和访问嵌套字典数据[重复]

在多个部署的情况下创建的单例实例的数量 [重复]

在vertx中跨顶点共享单例客户端的正确方法

如何跨模式和数据库对存储在表中的数据提供数据隔离/受控访问

JMeter接口测试-模块控制器

如何使用模块化代码片段中的LeakCanary检测内存泄漏?