在 Rust 中从不同的模块填充静态数组?

Filling a static array from different modules in Rust?

提问人:glasflügel 提问时间:7/17/2021 更新时间:7/17/2021 访问量:754

问:

在我的 Rust 项目中,我需要一个全局保持、静态数组或 vec,它初始化一次,模块可以在其中注册值或函数。我以为,使用 lazy_static!-crate 是可能的,但似乎并非如此。

这就是我想要实现的目标:

  • 模块使用一些数据初始化数组/vec。a
  • 然后,模块(或更多模块)将此数组/vec 扩展到更多数据。b
  • 所有这些应该只在程序启动时执行一次,并且在程序执行期间不会修改数组。它只是一个全局保存的查找表,但一旦从多个模块创建。

这是我的初稿,它不起作用 playground 链接

mod a
{
    use lazy_static::lazy_static; // 1.4.0

    lazy_static!{
        #[derive(Debug)]
        pub static ref TEST: Vec<u32> = vec![1, 2, 3];
    }
}

mod b  // when module b is removed, it works. 
{
    use lazy_static::lazy_static; // 1.4.0
    use crate::a::TEST;

    lazy_static!{
        TEST.extend(vec![4, 5, 6]);
    }
}

use a::TEST;

fn main() {
    for i in 0..TEST.len() {
        println!("{}", TEST[i]);
    }
}

谁能帮忙?

静态变量 惰性静态

评论

1赞 Cerberus 7/17/2021
您可能还对以下内容感兴趣 - docs.rs/linkme/0.2.6/linkme/struct.DistributedSlice.htmllinkme

答:

3赞 Jeremy Meadows 7/17/2021 #1

需要注意的几点:

  • 据我所知,是用于声明静态变量,所以不能像您在示例中尝试的那样仅使用宏来改变其他静态lazy_static!mod b
  • 为了使静态在 Rust 中可变,您需要将它们包装在一个 Rust 中,以遵循 Rust 保证线程安全的整个过程Mutex
  • modules旨在收集结构、函数、特征等内容,因此,如果你想让它们“做”某事,你需要在函数调用中拥有它。

话虽如此,我希望这个片段能帮助你。

Rust 游乐场

mod a {
    use lazy_static::lazy_static; // 1.4.0
    use std::sync::Mutex;

    lazy_static!{
        #[derive(Debug)]
        pub static ref TEST: Mutex<Vec<u32>> = Mutex::new(vec![1, 2, 3]);
    }
}

mod b {
    use crate::a::TEST;
    
    pub fn append_to_test() {
        TEST.lock().unwrap().extend(vec![4, 5, 6]);
    }
}

use a::TEST;

fn main() {
    crate::b::append_to_test();
    
    println!("{:?}", TEST.lock().unwrap());
}

评论

0赞 glasflügel 7/17/2021
谢谢,这正是我一直在寻找的解决方案!你是对的,我前段时间读过关于互斥锁的文章,但没有详细记住它。
0赞 glasflügel 7/19/2021
有没有办法在执行 main() 或对 crate 的任何测试之前自动调用 crate::b::append_to_test()?这是这种情况的另一个游乐场(重命名了一些函数):play.rust-lang.org/...
0赞 Jeremy Meadows 7/20/2021
从技术上讲,不可以,您不能在 之前执行代码,因为这是程序的入口点。但是,如果您只想在逻辑上将其分开,那么如果您运行的是 Rust Nightly,则可以使用 SyncLazy。这绝对不是最优雅的编写方式,因为我刚刚将一些代码硬塞到您的示例中,但是这个 playground 创建了一个全局静态,它包装 ,并调用方法。main()SyncLazya::ITEMS