跨异步闭包共享数据结构

Sharing data structures across async closures

我一直在尝试跨异步助手共享(只读)数据结构。我想要完成的是创建一个超级服务器,我在其中预先生成一些可供所有请求处理程序使用的数据。

这是 Hyper 入门指南中的示例,扩展了我正在尝试做的事情:

#[tokio::main]
async fn main() {
    let address = SocketAddr::from(([127, 0, 0, 1], 3000));

    let pages = generate_static_pages();

    let make_service = make_service_fn(|_conn| async move {
        Ok::<_, Infallible>(service_fn(|req: Request<Body>| async move {
            serve(pages, req)
        }))
    });

    let server = Server::bind(&address).serve(make_service);

    if let Err(error) = server.await {
        eprintln!("server error: {}", error);
    }
}

在我的例子中,generate_static_pages() returns 具有预生成页面的 HashMap<&'static str, Bytes>。不幸的是,这个哈希映射不能在编译时生成,因为那样会使事情变得容易得多。现在,我很挣扎,因为 pages 不能被闭包借用:"cannot move out of pages, a captured variable in an FnMut closure"

我试图传递一个引用,但这没有用,因为 Rust 无法推断变量的寿命足以让闭包使用。然后我尝试使用 .clone() 但这不起作用,因为它会在变量移动后调用它,但它不能。最后,我尝试用 Arc 包装,但这并没有解决问题,基本上是因为同样的原因。

你会建议我做什么?谢谢!

如果您只需要对页面的不可变引用,那么您应该能够使用 lazy_static crate。 lazy_static 允许您在运行时初始化静态变量 - 这非常有用!

您的代码最终会类似于:

use lazy_static::lazy_static;

lazy_static! {
  static ref PAGES: HashMap<&'static str, Bytes> = generate_static_pages();
}

#[tokio::main]
async fn main() {
    let address = SocketAddr::from(([127, 0, 0, 1], 3000));

    let make_service = make_service_fn(|_conn| async move {
        Ok::<_, Infallible>(service_fn(|req: Request<Body>| async move {
            serve(&PAGES, req)
        }))
    });

    let server = Server::bind(&address).serve(make_service);

    if let Err(error) = server.await {
        eprintln!("server error: {}", error);
    }
}

此外,还有一个 lazy_static example