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

How do I call a function that requires a 'static lifetime with a variable created in main?

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

impl MyStruct {
    pub fn doSomething(&'static self) {
        // Some code goes here
    }
}

我像这样从 main 消费它:

fn main() {
    let obj = MyStruct {};
    obj.doSomething();
}

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

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

有办法实现吗?

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

创建的变量
struct MyStruct;

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

static OBJ: MyStruct = MyStruct;

fn main() {
    OBJ.do_something();
}

随着 Rust 的持续求值故事的改进,这将更加常见,但它永远不允许在运行时进行配置。

一种不太常见的方法是故意泄漏内存,产生一个持续 "forever" 的引用。不鼓励这样做,因为内存泄漏不是一件好事:

fn main() {
    let obj = Box::leak(Box::new(MyStruct));
    obj.do_something();
}

也可以创建单例:

  • How do I create a global, mutable singleton?
  • How can you make a safe static singleton in Rust?

as once main is complete the application should exit.

也许吧,但是编译器不会将 main 特别地用于生命周期目的。


hyper requires a static runtime when running the server and processing each request.

不,不是。它有一个 : '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());
}

如果您想要动态重新配置,您甚至可以使用 interior mutability

另请参阅:

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

static mut OBJ: MyStruct = MyStruct;

fn main() {
    unsafe {
        OBJ = MyStruct {};
        OBJ.doSomething();
    }
}

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

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

use lazy_static::lazy_static;

fn main() {
    lazy_static!{
        static ref OBJ: MyStruct = MyStruct {};
    }
    OBJ.doSomething();
}