Global state is data accessible without being passed through a function or object interface. It can be convenient, but shared access can introduce race conditions, tight coupling, poor testability, and behavior that is hard to reason about. Use it sparingly, especially in libraries. section 4.6 section 10.7
Rust provides `static` and `const` globals, whose initial values must be determined at compile time. A `static` must be `Sync` for thread-safe access; changing a `static mut` requires `unsafe`. You cannot directly initialize a static `Vec<String>` with heap allocations. When global data needs that kind of initialization, lazy initialization is one option. section 4.6
error[E0010]: allocations are not allowed in statics
--> src/main.rs:1:47
|
1 | static POPULAR_BABY_NAMES_2021: Vec<String> = vec![
| _______________________________________________^
2 | | String::from("Olivia"),
3 | | String::from("Liam"),
4 | | String::from("Emma"),
5 | | String::from("Noah"),
6 | | ];
| |_^ allocation not allowed in statics
|
= note: this error originates in the macro `vec` (in Nightly builds,
run with -Z macro-backtrace for more info)
error[E0015]: cannot call non-const fn `<String as From<&str>>::from`
in statics
--> src/main.rs:2:5
|
2 | String::from("Olivia"),
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple
structs and tuple variants
= note: consider wrapping this expression in `Lazy::new(|| ...)`
from the `once_cell` crate: https://crates.io/crates/once_cell
The compiler errors show why allocating a vector and constructing strings directly in a static declaration does not work. section 4.6
For immutable global data, `lazy_static!` defines a `static ref` whose value is initialized lazily. Its `Deref` implementation permits access with `*`. If the data must change, a `Mutex` or `RwLock` can guard it. `once_cell` and `static_init` are other lazy-global options; `OnceCell` and the thread-safe `OnceLock` offer ways to initialize singletons. section 4.6.1 section 10.7
Listing 4.16 Popular baby names with lazy-static.rs
A lazily initialized vector makes the heap allocation possible without a direct static initializer. section 4.6.1
Before making state global, consider who should own it. A library can let callers build a context object and pass it to operations or modules. That makes configuration, caches, counters, or connection pools explicit, permits multiple independent instances, and eases testing. Passing arguments or using dependency injection can likewise avoid a singleton. If state must persist, provide serialization and deserialization rather than hiding its management. section 6.9 section 10.7
let ctx = MyLibrary::new() #1
.with_option(true)
.with_param(3.14)
.with_setting(249295)
.build(); #2
ctx.do_operation(); #3
let inner_module = MyLibrary::InnerModule::new(ctx); #4
inner_module.do_an_inner_operation(); #5
The builder-created context shows state passed to an inner module instead of stored globally. section 6.9






































