Rust中的静态结构

时间:2014-09-21 21:59:06

标签: static structure rust

我正在玩Nickel.rs来构建一个待办事项列表示例。由于暂时不支持闭包,我试图找到另一种处理我实现的简单结构的方法。

这是我的代码:

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);
}

但编译器给我写了这样的话:“不允许有可变的静态项目具有析构函数”

您对我如何解决这个问题有什么建议吗?

1 个答案:

答案 0 :(得分: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(){}范围内,其中定义了sample。

它仍然有效。