2014-09-21 92 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