将数据解析为模块级可变静态变量

时间:2015-03-03 05:51:32

标签: static rust mutability

我在模块中有一组需要访问某些共享初始化时间状态的函数。实际上,我想用静态可变矢量来模拟它,如:

static mut defs: Vec<String> = vec![];

fn initialize() {
    defs.push("One".to_string());
    defs.push("Two".to_string()); 
}

(示例:http://is.gd/TyNQVv,失败,“不允许使用可变静态的析构函数”。)

我的问题类似于Is it possible to use global variables in Rust?,但使用Vec(即带有析构函数的类型),因此基于Option的问题解决方案似乎不适用。也就是说,这失败的原因与我第一次尝试的错误相同:

static mut defs: Option<Vec<String>> = None;

fn initialize() {
    let init_defs = vec![];
    init_defs.push("One".to_string());
    init_defs.push("Two".to_string()); 
    defs = Some(init_defs);
}
  1. 有没有办法访问在初始化时填充并在运行时可见的静态(“全局”)向量?

  2. 我是否应该考虑其他模式来支持这个用例?传递对状态向量的显式引用是可能的,但会混乱大量的函数签名,这些函数签名都需要访问此状态。

1 个答案:

答案 0 :(得分:11)

您可以将lazy_static用于此目的:

lazy_static! {
    static ref defs: Vec<String> = {
        let mut init = vec!["One".to_string(), "Two".to_string()];
        // init.push(...); etc. etc.
        init
    }
}

在第一次访问时初始化一个向量,之后它是不可变的。如果您希望稍后修改它,将其包装在std::sync::Mutex中是一个很好的第一步。

  

我是否应该考虑其他模式来支持这个用例?传递对状态向量的显式引用是可能的,但会混乱大量的函数签名,这些函数签名都需要访问此状态。

要考虑的一种模式是创建一个上下文对象,它存储函数所需的所有信息,例如

struct Context {
    defs: Vec<String>
}

然后传递Context确保每个人都知道他们需要知道什么。您甚至可以考虑将所有/多个/部分函数作为方法放在Context上,例如

impl Context {
    fn foo(&self) {
        if self.defs.len() > 10 {
             println!("lots of defs");
        }
    }
    // ...
}

如果您需要修改上下文(自动确保线程安全),和/或您希望在单个进程中拥有多个独立实例,则此模式特别好。