Is there an easy way to implement Singleton object in Rust?

Is there an easy way to implement Singleton object in Rust?

Well, Rust is not an OOP language, so many OOP concepts are hard or un-idiomatic to implement.
If you'd tell why you need the singleton, perhaps you'd get better advice.
Buf if you really were to implement a Singleton, you'd need to figure out a way to make sure it is instantiated only once. I think that's easiest done with a global variable. Initially the global would be None and after first initialization, it would have the value. This can be achieved with a OnceCell.
That said, Singleton is a pattern that most OOP gurus suggest not to use. It hampers testing and introduces implicit global state. Its best avoided even more so in Rust.
What do you actually want to achieve?

4 Likes

Understand that In Rust it is not recommended to use Singleton. But there are some cases that we really need a singleton object, for example a logger instance. In my case, it is a run time env and the settings, I want to make sure that each program instance only has one env instance.

What I would do is create a type (e.g. Logger or Config) then store an instance of it in a static variable that gets initialized only once. You probably don't need to enforce it's singleton-ness (if that's a word) by construction, just make sure that static variable is accessible publicly.

use once_cell::sync::Lazy;
use std::collections::HashMap;

static CONFIG: Lazy<Config> = Lazy::new(|| Config::default());

#[derive(Debug, Default)]
struct Config {
    fields: HashMap<String, String>,
}

fn main() {
    use_config(&CONFIG);
}

fn use_config(cfg: &Config) {
    println!("{:?}", cfg);
}

(playground)

For something that needs to allow mutation (e.g. imagine loading values into the config from a file) then you would wrap the Config in a Mutex or RwLock.

use std::sync::RwLock;

static CONFIG: Lazy<RwLock<Config>> = Lazy::new(|| RwLock::new(Config::default()));

fn main() {
    let cfg = CONFIG.read().expect("lock was poisoned");
    use_config(&cfg);
}
2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.