Home
Rust
OnceCell Use
Updated Jun 21, 2023
Dot Net Perls
OnceCell. Suppose we have a struct that is expensive to initialize, and might not always be needed. Or we want to wait to initialize it until the last moment possible.
For lazy initialization in Rust, OnceCell is useful. It can help us write logic on a single thread that delays or avoids initializing an expensive type.
Example. Consider this program—like many real-world programs, it has some complicated logic in a function. It can be hard to determine when or if our Test struct is even needed.
Step 1 We create a OnceCell with the new() function. This does not initialize the Test struct inside of it yet.
struct
Step 2 We pass a OnceCell reference to a function. We can use a single OnceCell across many function calls.
Step 3 We use a for-range loop to iterate over a range of numbers. This makes the program more complicated to reason about.
for
Step 4 We initialize the OnceCell on 2 different conditions. It is only initialized once, even though it is accessed twice.
use std::cell::OnceCell; struct Test { value: String, } fn init_test(i: usize) -> Test { // Store value string in struct. Test { value: i.to_string(), } } fn main() { // Step 1: create OnceCell. let test = OnceCell::new(); // Step 2: pass OnceCell to function. compute(&test); } fn compute(test: &OnceCell<Test>) { // Step 3: loop over some numbers. for i in 1..100 { // Step 4: if one of two conditions is true, initialize the OnceCell if not already initialized. if i == 60 { let result = test.get_or_init(|| init_test(i)); println!("i = 60, value = {}", result.value); } if i % 61 == 0 { let result = test.get_or_init(|| init_test(i)); println!("i % 61 = 0, value = {}", result.value); } } }
i = 60, value = 60 i % 61 = 0, value = 60
Benefits. In a real-world Rust program, we have many functions and conditions. By lazily initializing a struct, we can save resources if the struct is never accessed.
And We can initialize only when needed, which makes our program easier to write and reason about later.
Single-thread. With OnceCell, we do not have a Sync trait so we cannot cross a thread barrier. This means OnceCell can only be used on a single thread, and it cannot be static.
Tip Consider OnceLock for a Sync-enabled version of OnceCell. OnceLock can be used a static and accessed on multiple threads.
OnceLock
By using OnceCell and its sibling OnceLock, we can simplify and optimize programs. We delay initialization, which means less setup logic is needed, and this can sometimes avoid work altogether.
Dot Net Perls is a collection of pages with code examples, which are updated to stay current. Programming is an art, and it can be learned from examples.
Donate to this site to help offset the costs of running the server. Sites like this will cease to exist if there is no financial support for them.
Sam Allen is passionate about computer languages, and he maintains 100% of the material available on this website. He hopes it makes the world a nicer place.
This page was last updated on Jun 21, 2023 (new).
Home
Changes
© 2007-2025 Sam Allen