2014-09-21 87 views
1

我在玩Nickel.rs來構建待辦事項列表示例。由於目前暫不支持關閉,我正試圖找到另一種方式來處理我實施的簡單結構。Rust中的靜態結構

這裏是我的代碼:

extern crate nickel; 

use std::io::net::ip::Ipv4Addr; 
use nickel::{Nickel, Request, Response}; 

struct TaskList { 
    list: Vec<String> 
} 

impl TaskList { 
    fn new() -> TaskList { 
     TaskList { list: Vec::new() } 
    } 

    fn add_task (&mut self, task: &str) { 
     &self.list.push(task.to_string()); 
    } 

    fn get_tasks (&self) -> Vec<String> { 
     self.list.to_vec() 
    } 
} 

fn main() { 
    let mut server = Nickel::new(); 

    static mut sample : TaskList = TaskList { list: Vec::new() }; 

    sample.add_task("First"); 
    sample.add_task("Second"); 

    fn fetch_tasks (_request: &Request, response: &mut Response) { 
     response.send(sample.get_tasks().to_string()) 
    } 

    server.utilize(Nickel::static_files("./public")); 

    server.get("/task", fetch_tasks); 
    server.listen(Ipv4Addr(127, 0, 0, 1), 6767); 
} 

但是,編譯器給我寫這樣的:「易變的靜態項目不允許析構函數」

你對我怎樣才能解決這個有什麼建議?

回答

0

我不太確定你想達到的目標。

如果您希望TaskList存在於堆上,請使用Box。然而,堆棧範圍應該是server.listen()內的有效事件,所以我不明白爲什麼你需要TaskList成爲一個靜態的mut?

如果你想更動靜態變量,你必須這樣做不安全,像這樣:

use std::mem::transmute; 
use std::ptr; 

struct Static { 
    v: int 
} 

impl Static { 
    fn whatever(&mut self) { 
    println!("Write to static"); 
    self.v += 1; 
    } 
} 

static mut _data:*const Static = 0 as *const Static; 

unsafe fn get<'a>() -> &'a mut Static { 
    if _data == ptr::null::<Static>() { 

    // Notice this is a Box<Static>, which is a *Static allocated on the heap 
    // transmute(Static { v: 0 }) wouldn't work because once the stack scope ends 
    // the instance would no longer be valid; Box<T> lasts beyond the call to get() 
    _data = transmute(box Static { v: 0 }); 
    } 
    return transmute(_data); 
} 

unsafe fn release() { 
    ptr::read::<Static>(_data); 
} 

impl Drop for Static { 
    fn drop(&mut self) { 
    println!("Dropped static"); 
    } 
} 

fn main() { 
    unsafe { 
    let foo = get(); 
    foo.whatever(); 
    } 
    unsafe { 
    let foo = get(); 
    foo.whatever(); 
    } 
    unsafe { 
    release(); 
    } 
    println!("Done"); 
} 

我真的強烈反對它雖然,除非有一個很好的理由。

大多數時候,你可以假設你在一個範圍內創建一個變量:

{ 
    let foo = Bar; 
    ... 
} <-- End 

將繼續有效,直至該範圍的結束。

像server.get這樣的子調用仍在定義樣本的main(){}範圍內。

它仍然有效。

+0

我首先假定,如果不將'sample'變量設置爲static,則可以在函數'fetch_tasks'中訪問(因爲它在main(){}中定義)。但編譯器告訴我,我無法捕捉'fetch_task'中的動態環境,所以我必須使用閉包。但是router.get()需要第二個參數的一個函數。 – 2014-09-22 13:23:46

+0

@ThomasC__您可能需要使用「中間件」,以便您可以在給定「請求」上下文的情況下訪問「TaskList」的句柄。也許看看一些中間件的例子。 – BurntSushi5 2014-09-23 11:39:23