liveBook · Manning

Lazy_static

As explained in Learn Rust in a Month of Lunches

lazy_static is a Rust crate that provides statics initialized on first runtime access when compile-time constant initialization is insufficient.

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

How Learn Rust in a Month of Lunches covers it

How deep it goes
Explains syntax, generated dereference behavior, compiler failures, and a working logger, while deferring deeper macro internals.
Examples
Uses a global Logger with a Mutex-protected log vector, URL String, reqwest Client, compiler errors, and a completed logging program.
What it assumes
Assumes basic Rust statics and const functions, then teaches why non-const initialization requires lazy_static.
What you can do after
Apply it via the lazy_static crate to define and access global values requiring runtime construction.
How it connects
Connects lazy_static with statics, const fn, once_cell, Mutex, heap allocation, and runtime function calls.

Also explained in

Compare how 2 books explain lazy_static →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Rust in a Month of Lunches. The section links point to the parts of the book it draws on.