2015-03-03 47 views
5

我有一組模塊內需要訪問一些共享的初始化時間狀態的功能。有效地我想要像一個靜態可變矢量模型如下:解析數據到模塊級別的可變靜態變量

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. 我還有其他應該考慮支持這種用例的模式嗎?傳遞狀態向量的顯式引用是可能的,但會混淆大量需要訪問此狀態的函數簽名。

回答

9

您可以使用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"); 
     } 
    } 
    // ... 
} 

這種模式是特別好,如果你需要修改上下文(自動保證線程安全),和/或如果你想有幾個獨立的情況下,在一個單一的過程。

+1

謝謝!這非常清楚地回答了我的兩個問題。我特別喜歡上下文結構模式,使用'impl''方法。這感覺更習慣。 – Bosh 2015-03-03 21:01:48