跨多个模块访问单例

时间:2018-08-31 02:40:24

标签: scope rust singleton

我正在尝试使用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);
}

是否可以在所有模块中创建全局变量?我还有其他思考方式吗?也许不经常使用模块?

2 个答案:

答案 0 :(得分:2)

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

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

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

Rust中的静态变量

在Rust中,我们通常避免使用静态变量。在大多数情况下,可以通过const将它们替换为适当的常量。由于静态变量可能在线程之间共享,因此在Rust中,使它们具有外部可变性是unsafe。这就是为什么lazy_static无法具有外部可变性。

尽管具有外部可变性的静态变量确实有其用途,但它们是特定的,应加以说明,否则应避免使用。 this section of the Rust Book中所述的内部可变性甚至不允许在线程之间共享。

Rust中的单一模式

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

需要不变数据的解决方案

  1. 使用const使其恒定。

  2. 如果数据太多,请使用static

  3. 如果需要非恒定初始化,则可以保持lazy_static。

需要突变数据的解决方案

  1. 将单身人士放入Mutex或其他锁中。这将确保正确的并发访问。

  2. 使用thread_local macro + inner mutability with RefCell

  3. 使其成为本地线程
  4. 放弃“单一模式”的想法,并通过参数传递结构(推荐)。

答案 1 :(得分:0)

您需要use才能将GAMEDATA导入到当前范围中,如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