如何使用在 main 中创建的变量调用需要“静态生命周期”的函数?

lyp*_*ptt 16 lifetime rust

我定义了一个结构,它有一个定义静态生命周期的函数:

impl MyStruct {
    pub fn doSomething(&'static self) {
        // Some code goes here
    }
}
Run Code Online (Sandbox Code Playgroud)

我像这样从 main 消费它:

fn main() {
    let obj = MyStruct {};
    obj.doSomething();
}
Run Code Online (Sandbox Code Playgroud)

它用于doSomething在应用程序的生命周期内阻塞和执行的调用。

我遇到了生命周期检查的问题,它指出它可能比main函数的寿命更长,这对我来说似乎很奇怪,因为一旦main完成应用程序应该退出。

有没有办法实现这一目标?

She*_*ter 12

创建具有生命周期的引用的主要方法是创建'static变量static。静态变量是可以在编译时创建的变量:

struct MyStruct;

impl MyStruct {
    pub fn do_something(&'static self) {}
}

static OBJ: MyStruct = MyStruct;

fn main() {
    OBJ.do_something();
}
Run Code Online (Sandbox Code Playgroud)

随着 Rust 的不断评估故事的改进,这将变得更加普遍,但它永远不会允许在运行时进行配置。

一种不太常见的方法是故意泄漏内存,产生一个“永远”持续的引用。这应该是不鼓励的,因为泄漏内存不是一件好事:

fn main() {
    let obj = Box::leak(Box::new(MyStruct));
    obj.do_something();
}
Run Code Online (Sandbox Code Playgroud)

也有可能创建一个单例:

一旦main完成,应用程序应该退出。

也许吧,但编译器并没有main专门针对终生目的进行处理。


hyper 在运行服务器和处理每个请求时需要一个静态运行时。

不,它没有。它的边界为: 'static,这意味着传入的任何引用都必须是'static,但您根本不必传入裸引用。

对于这样的模式,最常见的事情是传入类似Arc. 这允许共享底层资源。

pub fn do_something<F, T>(f: F)
where
    F: Fn() -> T + 'static,
    T: 'static,
{
    // "spawn" 3 threads
    f();
    f();
    f();
}

struct MyStruct;

static OBJ: MyStruct = MyStruct;

fn main() {
    // OK
    do_something(|| &OBJ);

    // Not OK
    let another = MyStruct;
    do_something(|| &another);

    // OK
    use std::sync::Arc;
    let shared = Arc::new(MyStruct);
    do_something(move || shared.clone());
}
Run Code Online (Sandbox Code Playgroud)

如果您想要动态重新配置,您甚至可以使用内部可变性

也可以看看:


Pet*_*all 10

最简单的方法是使用static变量,但如果您需要在main函数中实际设置值,则需要不安全的代码:

static mut OBJ: MyStruct = MyStruct;

fn main() {
    unsafe {
        OBJ = MyStruct {};
        OBJ.doSomething();
    }
}
Run Code Online (Sandbox Code Playgroud)

之后它也unsafe可以用可变静态做几乎任何事情。

更好的方法是让库 ( lazy_static) 处理不安全的代码。

#[macro_use]
extern crate lazy_static;

fn main() {
    lazy_static!{
        static ref OBJ: MyStruct = MyStruct {};
    }
    OBJ.doSomething();
}
Run Code Online (Sandbox Code Playgroud)