初始化传递给异步代码(例如 tokio 和 hyper)的 Rust 变量
Initializing a Rust variable passed to async code such as tokio and hyper
我有一个无法在编译时计算的值。它需要在任何应用程序代码 运行 之前计算,然后它只会在应用程序的整个生命周期中被读取。它还需要传递给执行程序,例如 tokio
和 hyper
处理程序。
我怎样才能安全、惯用地创建这样的值,而不会造成不必要的性能损失?
- 如果我在
main
中创建它并将其传递给 hyper
,它的寿命不够长。
- 如果我使用
lazy_static!
创建它,它只会在首次访问时进行计算。如果无法计算,那么我也不想 运行 应用程序的其余部分。我宁愿知道在启动应用程序时我无法连接到数据库,而不是在客户端发出请求时。
- 如果我将它设为
static mut
,那么我将无法在安全代码中使用它。
理想情况下,我想做类似的事情:
#[tokio::main]
pub async fn main() {
let db = init_db();
// This uses a hyper server, passes db around
// to tokio and hyper handlers, etc.
run_app(&db);
}
您可以将数据包装在 Arc
中,这样您的数据就可以共享,并且它会一直存在,直到没有任何引用为止:
use tokio::prelude::*;
use tokio;
use std::sync::Arc;
async fn init_db() -> Arc<String> {
Arc::new("Foo".to_string())
}
async fn run_app(data: Arc<String>) {
for _ in 0..10 {
println!("{}", data);
}
}
#[tokio::main]
pub async fn main() {
let db = init_db().await;
// This uses a hyper server, passes db around
// to tokio and hyper handlers, etc.
run_app(db).await;
}
您可以泄漏内存,使引用具有 'static
生命周期:
#[tokio::main]
pub async fn main() {
let db = Box::leak(Box::new(init_db())) as &'static _;
// This uses a hyper server, passes db around
// to tokio and hyper handlers, etc.
run_app(db);
}
If I create it with lazy_static!
, it only gets computed when it's first accessed.
当惰性静态变量是 initialize
d:
时,有一个特定的函数来控制
use lazy_static::lazy_static; // 1.4.0
lazy_static! {
static ref THING: String = String::from("a");
}
#[tokio::main]
pub async fn main() {
lazy_static::initialize(&THING);
run_app();
}
我有一个无法在编译时计算的值。它需要在任何应用程序代码 运行 之前计算,然后它只会在应用程序的整个生命周期中被读取。它还需要传递给执行程序,例如 tokio
和 hyper
处理程序。
我怎样才能安全、惯用地创建这样的值,而不会造成不必要的性能损失?
- 如果我在
main
中创建它并将其传递给hyper
,它的寿命不够长。 - 如果我使用
lazy_static!
创建它,它只会在首次访问时进行计算。如果无法计算,那么我也不想 运行 应用程序的其余部分。我宁愿知道在启动应用程序时我无法连接到数据库,而不是在客户端发出请求时。 - 如果我将它设为
static mut
,那么我将无法在安全代码中使用它。
理想情况下,我想做类似的事情:
#[tokio::main]
pub async fn main() {
let db = init_db();
// This uses a hyper server, passes db around
// to tokio and hyper handlers, etc.
run_app(&db);
}
您可以将数据包装在 Arc
中,这样您的数据就可以共享,并且它会一直存在,直到没有任何引用为止:
use tokio::prelude::*;
use tokio;
use std::sync::Arc;
async fn init_db() -> Arc<String> {
Arc::new("Foo".to_string())
}
async fn run_app(data: Arc<String>) {
for _ in 0..10 {
println!("{}", data);
}
}
#[tokio::main]
pub async fn main() {
let db = init_db().await;
// This uses a hyper server, passes db around
// to tokio and hyper handlers, etc.
run_app(db).await;
}
您可以泄漏内存,使引用具有 'static
生命周期:
#[tokio::main]
pub async fn main() {
let db = Box::leak(Box::new(init_db())) as &'static _;
// This uses a hyper server, passes db around
// to tokio and hyper handlers, etc.
run_app(db);
}
If I create it with
lazy_static!
, it only gets computed when it's first accessed.
当惰性静态变量是 initialize
d:
use lazy_static::lazy_static; // 1.4.0
lazy_static! {
static ref THING: String = String::from("a");
}
#[tokio::main]
pub async fn main() {
lazy_static::initialize(&THING);
run_app();
}