lazy_static is a Rust crate for creating global statics when initialization needs runtime work instead of only compile-time constants. This includes heap allocations and function calls. section 17.7 section 17.7.1
Use the lazy_static! macro and declare a static ref. The crate uses that term for a generated, dereferenceable static; Rust itself has no separate static ref construct. section 17.7.1
The usual decision is straightforward:
- Use an ordinary static when its value can be initialized with const functions. section 17.7
- Use lazy_static when initialization needs operations such as String conversion, vector creation, or constructing a client. section 17.7.1
- Choose once_cell when you need a more flexible alternative; lazy_static is the older and simpler option. section 17.7
A global logger
A Logger containing a Mutex<Vec<Log>>, a String URL, and a reqwest::Client cannot be initialized as an ordinary static because to_string and Client::default are not const functions. Wrapping the definition in lazy_static! makes GLOBAL_LOGGER available throughout the program; the example locks its logs, pushes a message, and prints them. section 17.7.1
use lazy_static::lazy_static;
use reqwest::Client;
use std::sync::Mutex;
#[derive(Debug)]
struct Logger {
logs: Mutex<Vec<Log>>,
url: String,
client: Client,
}
#[derive(Debug)]
struct Log {
message: String,
timestamp: i64,
}
lazy_static! {
static ref GLOBAL_LOGGER: Logger = Logger {
logs: Mutex::new(vec![]),
url: "https://somethingsomething.com".to_string(),
client: Client::default()
};
}
fn main() {
GLOBAL_LOGGER.logs.lock().unwrap().push(Log {
message: "Everything's going well".to_string(),
timestamp: 1658930674
});
println!("{:#?}", *GLOBAL_LOGGER.logs.lock().unwrap());
}
Inspect the complete lazy_static! logger, including the static ref declaration, Mutex access, log insertion, and output. section 17.7.1

