Skip to main content

What It Is

The Singleton pattern makes sure a type has exactly one instance in the whole program, and gives everyone the same access point to it. Typical singletons: a configuration, a connection pool, a logger.

Go's tool for this is sync.Once: the initialization code inside once.Do() runs exactly once, even when many goroutines ask at the same time.


Example: One Config for Everyone

The config is loaded on the first GetConfig() call and never again. Every caller receives the same pointer.

Load once with sync.Once

The "loading config" line prints only once, although GetConfig() is called twice — and a == b proves both callers hold the same instance.

Prompt
Write a Go program with a Config singleton: a GetConfig function using sync.Once so the config is loaded exactly once, printing a line during loading. Call GetConfig twice, print the app name and prove both calls return the same instance by comparing the pointers.
Output: Go program and captured output

When to Use It

Use it when there really must be one of something: one loaded configuration, one connection pool, one cache — and creating it is expensive or duplicates would conflict.

Skip it when you can simply create the value in main() and pass it to whoever needs it. Passing dependencies openly is clearer than global access — the singleton is the last resort, not the first.


Pros and Cons

Pros: guaranteed single instance; lazy creation on first use; safe with many goroutines via sync.Once.

Cons: it is a global in disguise — hidden dependencies make code harder to follow; tests cannot easily swap it for a fake; overuse leads to tangled programs.