我正在尝试使用 lazy_static crate 创建一个单例并在不同的模块中使用它。这是可能的,甚至是推荐的吗?我仍在学习 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
时,我得到
not found in this scope
例如在名为 game
的模块中
pub struct Game {}
impl Game {
println!("data{}", GAMEDATA.width);
}
是否可以在所有模块中创建一个全局变量?我应该考虑其他方法吗?也许不经常使用模块?
如果您的静态变量在另一个非父模块中,您的问题似乎是在 static
之前缺少 pub
修饰符。此外,正如其他人指出的那样,您使用变量的代码(impl
block )不是有效的 Rust 语法。
除此之外,您还需要使用use
导入静态变量(例如use GAMEDATA;
),参见Quan Brew's answer .
但是,我想讨论一下 Rust 中静态和单例模式的使用。
Rust 中的静态变量
在 Rust 中,我们通常避免使用静态变量。在大多数情况下,它们可以通过 const
替换为适当的常量。因为静态变量可以在线程之间共享,所以让它们具有外部可变性在 Rust 中是不安全的
。这就是为什么不能使用 lazy_static 实现外部可变性的原因。
虽然具有外部可变性的静态变量确实有它们的用处,但它们是特定的,应该被证明是合理的,否则应该避免。内部可变性,如 this section of the Rust Book 中所述甚至不允许在线程之间共享。
Rust 中的单例模式
我不认为使用 static 来实现单例模式是个好主意。这种模式在 Rust 中并不常见。我们通常将所有可变的东西作为参数传递。
如果您需要不可变数据的解决方案
用const
让它成为常量。
如果数据太多,使用static
。
如果需要非常量初始化,可以保留lazy_static。
如果你需要改变数据的解决方案
将您的单例放入Mutex
或其他锁中。这将确保正确的并发访问。
使用 thread_local macro 使其成为本地线程+ inner mutability with RefCell
放弃“单例模式”的想法,通过参数传递结构(推荐)。