Singleton in go
Design PatternsGoSingletonAnti PatternsDesign Patterns Problem Overview
How does one implement the Singleton design pattern in the go programming language?
Design Patterns Solutions
Solution 1 - Design Patterns
Setting aside the argument of whether or not implementing the singleton pattern is a good idea, here's a possible implementation:
package singleton
type single struct {
O interface{};
}
var instantiated *single = nil
func New() *single {
if instantiated == nil {
instantiated = new(single);
}
return instantiated;
}
single
and instantiated
are private, but New()
is public. Thus, you can't directly instantiate single
without going through New()
, and it tracks the number of instantiations with the private boolean instantiated
. Adjust the definition of single
to taste.
However, as several others have noted, this is not thread-safe, unless you're only initializing your singleton in init()
. A better approach would be to leverage sync.Once
to do the hard work for you:
package singleton
import "sync"
type single struct {
O interface{};
}
var instantiated *single
var once sync.Once
func New() *single {
once.Do(func() {
instantiated = &single{}
})
return instantiated
}
See also, hasan j's suggestion of just thinking of a package as a singleton. And finally, do consider what others are suggesting: that singletons are often an indicator of a problematic implementation.
Solution 2 - Design Patterns
The best approach will be:
package singleton
import "sync"
type singleton struct {
}
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}
You should read this Link
Solution 3 - Design Patterns
Just put your variables and functions at the package level.
Also see similar question: How to make a singleton in Python
Solution 4 - Design Patterns
I think that in a concurrent world we need to be a bit more aware that these lines are not executed atomically:
if instantiated == nil {
instantiated = new(single);
}
I would follow the suggestion of @marketer and use the package "sync"
import "sync"
type MySingleton struct {
}
var _init_ctx sync.Once
var _instance *MySingleton
func New() * MySingleton {
_init_ctx.Do( func () { _instance = new(MySingleton) } )
return _instance
}
Solution 5 - Design Patterns
Before trying to find a way to bend Go to your will, you might want to take a look at some articles:
In summary, over time people have found singletons to be less than optimal, and imho especially if you are trying to do any test-driven development: on many levels they are pretty much as bad as global variables.
[disclaimer: I know its not a strict answer to your question but it really is relevant]
Solution 6 - Design Patterns
Easy peasy as you can see in the following code:
package main
import (
"fmt"
"sync"
)
type singleton struct {
count int
sync.RWMutex
}
var instance singleton
func GetInstance() *singleton {
return &instance
}
func (s *singleton) AddOne() {
s.Lock()
defer s.Unlock()
s.count++
}
func (s *singleton) GetCount() int {
s.RLock()
defer s.RUnlock()
return s.count
}
func main() {
obj1 := GetInstance()
obj1.AddOne()
fmt.Println(obj1.GetCount())
obj2 := GetInstance()
obj2.AddOne()
fmt.Println(obj2.GetCount())
obj3 := GetInstance()
obj3.AddOne()
fmt.Println(obj3.GetCount())
}
Expected result would be:
> 1 2 3
Because you're accessing to the same resource. That's the reason I've added mutex in order to be concurrent proven accessing count attribute from multiple processes. :-)
Source:
Solution 7 - Design Patterns
You can do initialization using the once package:
This will ensure that your init methods only get called once.
Solution 8 - Design Patterns
Just have a single static, final, constant, global, application-wide instance of the Object you want.
This however contradicts the OO paradigm. Its use should be limited to primitives and immutable objects, not to mutable objects.
Solution 9 - Design Patterns
You should be aware that Once.Do
is serious about executing the code only once. That means, the code is always executed only once, even though it might have panicked:
from https://golang.org/pkg/sync/#Once.Do
> If f (note: the once logic) panics, Do considers it to have returned; future calls of Do return without calling f.
I used mutexes instead to ensure unique initialisation of a global configuration variable to overcome this restriction:
Solution 10 - Design Patterns
I think if you want something like a singleton in Go you should try and think about what you're trying to achieve. Unlike Java or C#, Go has no concept of "static" classes, so the traditional distinction is less clear. In my mind, the key point you'd want from a singleton is not allowing others to construct it. To that end, I think it can achieved more simply: export an interface, implement an unexported class which implements this interface, and export a single instance of it. For instance:
var DefaultTransformer Transformer = &transformer{}
type Transformer interface {
Transform(s string) string
}
type transformer struct {
}
func (t *transformer) Transform(s string) string {
return s + "1"
}
var _ Transformer = (*transformer)(nil)
As the other answers show, there are many more literal ways you can implement the singleton pattern in Go, but they strike me as answers that start from the premise that the pattern must be copied exactly, rather than starting from solving a real problem you have in Go.