【问题标题】:Static struct in RustRust 中的静态结构
【发布时间】:2014-09-21 21:59:05
【问题描述】:

我正在使用 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);
}

但是编译器给我写了这个:“可变静态项不允许有析构函数”

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

【问题讨论】:

    标签: static structure rust


    【解决方案1】:

    我不太确定你想要达到什么目的。

    如果您希望 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 这样的子调用仍在定义 sample 的 main() { } 范围内。

    它仍然有效。

    【讨论】:

    • 我首先假设不将“sample”变量设为静态,它可以在函数“fetch_tasks”中访问(因为它是在 main() {} 中定义的)。但是编译器告诉我我无法在“fetch_task”中捕获动态环境,所以我必须使用闭包。但是 router.get() 的第二个参数需要一个函数。
    • @ThomasC__ 您可能需要使用“中间件”,以便在给定Request 上下文的情况下访问TaskList 的句柄。也许看看一些中间件的例子。
    猜你喜欢
    • 1970-01-01
    • 2011-03-02
    • 1970-01-01
    • 2021-04-25
    • 2011-10-28
    • 2015-06-07
    • 1970-01-01
    • 2013-02-05
    • 1970-01-01
    相关资源
    最近更新 更多