
Singleton Pattern in Go - mcastilho
http://marcio.io/2015/07/singleton-pattern-in-go/
======
colin_mccabe
It's funny how you can take an obvious antipattern (global variables) and turn
it into a pattern by giving it a cool new name like "Singleton". In this
spirit, I propose "the ProgramCounterAmbulator" as a cool new name for "goto."

Actually, gotos are usually less harmful than globals. At least they don't
interfere with unit testing the way globals tend to.

~~~
ignoramous
No argument that Singletons make it difficult to unit test things but there
are genuine cases where singletons are required: For instance, you don't want
to end up creating multiple objects that read the configuration file, when one
is enough. Or you certainly don't want to create too many objs that are heavy
(like a cache that stores data heavy objects, or services, or god-objects
(which are themselves an anti-pattern unavoidable in certain cases)).

At times, there's genuinely only a single entity of "x" that's available for
use by the environment, like a security-policy, or access to standard-output,
and so on...

Singletons are necessary evil, IMO.

Re: Global state: At some point the abstraction will have to leak. If you
squint enough, nothing is truly isolated, and everything's sharing everything
else with other binaries on any given system at some abstraction level or the
other. This is more often the reason why security-exploits are theoretically
possible despite isolation.

~~~
kentonv
Depends on what you mean by "singleton". If you define it loosely as "a type
of which there is only one instance", fine, no problem -- of course those will
exist. But if you define it as "globally-accessible mutable state", then the
problems start. Usually, the "singleton pattern" is explicitly a technique for
doing the latter.

> For instance, you don't want to end up creating multiple objects that read
> the configuration file, when one is enough.

Sure. But that doesn't mean the config file reader has to be globally-
accessible. Instead, try allocating it on the stack in your main() function,
then passing the object into each component that needs to see it. Better yet,
only pass each component a sub-object(s) of the config which applies
specifically to that component.

Now you have a bunch of useful benefits:

\- Readability: You can clearly see and follow what components are affected by
what parts of the config file.

\- Testability: Unit tests can easily provide a test configuration.

\- Maintainability: If some day you realize that you need to create two
instances of some component and configure them differently, it's easy to do
that without rewriting tons of code or introducing horrible "namespacing"
hacks.

\- Security: If your config file contains anything sensitive (say, database
credentials), it's no longer the case that every damned module in the whole
system has the ability to read those secrets. In fact, if your language is
memory-safe and bans mutable global state, you can trivially sandbox any piece
of code by simply not passing it references to anything it shouldn't be able
to access. (This is called "capability-based security" or "object
capabilities", and it works.)

Extended argument (which I wrote many years ago...):

[http://www.object-oriented-security.org/lets-
argue/singleton...](http://www.object-oriented-security.org/lets-
argue/singletons)

~~~
readme
Nailed it. It's fine to use a singleton, but don't call it from within every
class you use it in. Just pass a reference to the instance of the singleton.
Call it once in the outermost scope.

~~~
Lorento
Just wondering what value the singleton provided if you only obtain it once.
Isn't the purpose so you can obtain it whenever you want? If you just use a
regular object, you run the risk of accidentally making another instance
somewhere else, but you always have that risk with any regular object anyway.

~~~
readme
It's kind of OK to use, as long as you don't call it all over the place and
render your code untestable such that it can't be mocked out, but I'm not a
huge fan of it. It's really a matter of opinion at that point.

------
codahale
It’s worth noting that not only do you need to synchronize access to the
singleton, you need to synchronize access to the singleton’s state as well.
And even if you manage that at a fine-grained layer, you’re still setting
yourself up for all the problems associated with singletons:
[http://c2.com/cgi/wiki?SingletonsAreEvil](http://c2.com/cgi/wiki?SingletonsAreEvil).

If you have a bunch of immutable state, then build unexported package
variables in the package’s `init` func and export funcs which use those
variables.

If you have a bunch of mutable state, then don’t use a singleton.

~~~
lemevi
Do you think it would be fine to use a singleton if the writes are all
happening in a single thread and it's not critical that the reads be
synchronized? Sharing state across go routines seems like something to be
avoided. In vanilla Java it's always not easy to avoid sharing state.

~~~
codahale
If you want your reads to ever work, then they need to be synchronized.
Reading from an unfenced address during concurrent writes is undefined
behavior for any CPU architecture you can think of, which means you’ll get
stale reads _in a best-case scenario_. You can also get garbage reads (e.g. as
your CPU interprets your read of a 64-bit pointer as two 32-bit reads),
crashes, bees, etc.

The code you write is either thread-safe, used in a single-threaded context,
or a pinless grenade.

~~~
pcwalton
There are exceptions to this rule--i.e. there are ways to not really be
thread-safe but to have things work anyway--but they fall in the category of
"you have to really, really know your CPU and be willing to write processor-
specific code that just happens to work", so you can basically ignore them.

My favorite is the libdispatch abuse of cpuid to flood the pipeline on Intel
CPUs for this problem: [https://www.mikeash.com/pyblog/friday-
qa-2014-06-06-secrets-...](https://www.mikeash.com/pyblog/friday-
qa-2014-06-06-secrets-of-dispatch_once.html)

But really, take Coda's advice. If you aren't synchronizing your reads, you
can basically just assume your code is broken.

~~~
twic
An interesting exception is Lamport's Bakery:

[https://en.m.wikipedia.org/wiki/Lamport%27s_bakery_algorithm](https://en.m.wikipedia.org/wiki/Lamport%27s_bakery_algorithm)

Thread safety without synchronisation primitives. I'm not sure it's ever
actually a good idea to use it, though.

EDIT: unless you count a fence as a synchronisation primitive.

------
pcwalton
Your "check-lock-check" code is probably broken (depending on the intricacies
of Golang's memory model). If the compiler or CPU reorders any stores to the
fields of "instance" after the assignment to "instance" itself, other threads
could start working with a partially uninitialized object. Once() uses atomics
on the fast path for a reason.

~~~
skrap
Totally! I was going to post the same thing. Double-checked locking is either
impossible or really hard to get right, depending on the language and
architecture's guarantees!

If you must use a singleton, I'd really recommend doing the so-called
"aggressive" approach, which should have really been named the "actually won't
crash sometimes" approach.

~~~
jaytaylor
+1 for the aggressive approach, mutexes are very fast in go.

I got curious and wrote a quick little benchmark test:

    
    
        $ cat bench_test.go
        package main
        
        import (
        	"sync"
        	"testing"
        )
        
        func BenchmarkMutex(b *testing.B) {
        	var m sync.Mutex
        	for n := 0; n < b.N; n++ {
        		m.Lock()
        		m.Unlock()
        	}
        }
    
    
        $ go test -v -bench=. bench_test.go
        BenchmarkMutex	50000000	        24.0 ns/op
        ok  	command-line-arguments	1.235s
    

A set of mutex.Lock() & .Unlock() calls takes only 24.0ns on average to
complete.

Thus it's possible to lock/unlock more than 41 million times per second on the
puny 2011 MacBook Air I used for this.

My .02c:

The post seems like a case of premature optimization.

Resource bottlenecks due to too much mutex locking in go does not seem like a
case that will be commonly hit.

With infinite potential bottlenecks, I don't like to spend my time worrying
and fussing over things that are:

A) Not yet a problem.

B) Unlikely to ever be a problem or give me grief.

Worrying about the overhead cost of locking falls squarely into just such a
category.

~~~
jsprogrammer
This has no contention and is essentially a no-op? Or do I not understand go?

~~~
pcwalton
It is a no-op, but Golang's Plan 9-based compilers don't do much optimization,
so they aren't able to eliminate it.

------
tptacek
This is cute, but I think (someone will correct me if I'm wrong) that the real
idiom is: things that would be singletons in Java are instead servers managing
a channel in Golang.

~~~
ffk
Why incur the cost and complexity of a channel if what you are doing doesn't
require it? Go's sync.Once just implements the check-lock-check pattern. It
doesn't use a channel in the background.

In fact, it is better to use sync.Once to reduce the risk getting the
semantics of check-lock-check incorrect. :)

[edit: It occurred to me that the parent may be speaking about architecture
and not about the singleton's design. From an architectural perspective, there
are much better patterns in golang than a singleton.]

~~~
tptacek
The architecture! Not the design of this singleton.

------
jmount
I thought there was a lot of literature pretty convincingly arguing that
singleton is in fact an anti-pattern.

~~~
inglor
There is, singletons are an anti-pattern, they're still interesting to discuss
like this in terms of making them safe. In a language with both concurrency
primitives and globals singletons have little (no) place anyway. I still
learned from the post.

~~~
jsprogrammer
Shouldn't there be a disclaimer though?

Or, at least an example of when it would be a good idea to use a singleton
over some other pattern?

------
vortico
What's the point of a singleton when you can just have variables in an
anonymous struct at root level, and functions defined at root as well?

    
    
      var server struct {
      	host string
      	port string
      }
      
      func serverStart() {
      	server.host = "..."
      	server.port = "..."
      }

~~~
pcwalton
When do you call "serverStart()"? If the answer is "eagerly during startup",
there's no problem (other than startup time, of course). If the answer is "on
demand", now you have a synchronization problem.

------
hendzen
This post is chock-full of antipatterns. Both the singleton pattern and double
checked locking should be avoided.

~~~
hesdeadjim
Yea it's easy enough to use dependency injection to satisfy these supposedly
"global" requirements. About the only global state I can tolerate is read-only
constants, but even then you are much better off with DI just because of
testing.

~~~
bkeroack
DI is an antipattern.

~~~
aikah
who told you that? you'd better not listen to that guy anymore.

------
strictfp
Coding Pro Tip: Instead of using the Singleton pattern, make one instance of
your class at the start of your program and pass it around to its users.

Singletons are really just as bad as global variables. Why? Because they are
global variables.

~~~
nadams
Depending on what you are trying to implement - passing an extra variable
everywhere is just creating noise (because potentially you have to have an
extra parameter to EVERY function or method). I believe in KISS - everything
should be as simple as possible but not simpler. Believe it or not there are
valid uses for a Singleton which, many would agree, include a simple logging
class [1].

One could argue that you could just create it in the section of code you want
to log - but that just creates noise and you end up repeating code.

logger = Log() # run code to open the file to the last position
logger.log("test")

vs

Log.instance().log("test")

Now imagine this was a multi-threaded application - singleton arguments are
much different.

> Singletons are really just as bad as global variables. Why? Because they are
> global variables.

Everyone has their own opinions - but you can't make sweeping generalizations.
I'm not saying a global variable is appropriate in every situation - but every
language, and project, is different. There are even different dialects of C++
[2].

[1] - [http://stackoverflow.com/questions/228164/on-design-
patterns...](http://stackoverflow.com/questions/228164/on-design-patterns-
when-to-use-the-singleton)

[2] -
[http://www.reddit.com/r/programming/comments/197dn1/introduc...](http://www.reddit.com/r/programming/comments/197dn1/introduction_to_c_a_series_of_46_videos_created/c8lks22)

~~~
alangpierce
> you have to have an extra parameter to EVERY function or method

Dependency injection provides a pretty good solution to this, potentially even
for the logging use case. Classes (or code modules or whatever) only need to
think about their _direct_ dependencies, and indirect dependencies are handled
naturally by the wiring code. In a well-written codebase using DI, you
basically never need to write code that accepts an argument just so that it
can pass that argument down to other code.

For example, if a class Foo deep in your program wants to use an interface
called Logger for the first time, you just add a Logger as a field and pass
the Logger into the Foo constructor in your wiring code. It's a little more
ceremony than an import statement, but not by much, especially if you use a DI
framework to do the wiring for you. Importantly, you don't need to make any
changes to code that uses Foo.

An advantage to this approach is that it makes it easier to test usage of
Logger (e.g. asserting that Foo logs an error in a particular situation). It
also makes it easier to extend the Logger, like using a Logger wrapper that
collects statistics on what was logged, without needing a special
extensibility point in the Logger implementation.

That's not to say globals/singletons are always a bad idea. They tend to
result in shorter code and they're easier to understand, and you can still
test against them if you're willing to use mutable singletons (e.g. monkey
patching in Python) or custom extensibility points. My main point is that, if
you have a class that's useful in a wide variety of situations, there are
other solutions than just "use a global" and "explicitly pass it around
everywhere", and IMO dependency injection is one of the best options if you're
writing serious code.

------
TheMagicHorsey
Wouldn't it make more sense to have some sort of manager that receives
information on an incoming channel, manages the state internally, and reports
out on an outgoing channel?

~~~
jerf
Abstractly, if you somehow need a singleton object, this will be substantially
faster if you need it frequently. And if you're careful to do all the other
things you need to do in order to make this work and safe, as seen in the
other messages in this post.

Practically, all the examples I've ever of why you'd ever want a singleton are
indeed better done as a goroutine server over channels. Within the object you
get an implicit lock by virtue of being the only goroutine ever to touch that
stuff, and as long as you don't need this object to use more than one CPU
total and the overhead of channels isn't a big deal, which again, describes
the vast bulk of cases I've ever heard of that call for singletons, it's a
better way to go.

And I'd note I've written a couple dozen different goroutine server things and
a grand total of 0 'singletons', so... yeah.

If I had an immutable singleton object that was somehow very expensive to
initialize, I might consider this approach. Not sure when that would come up
but I'm sure it describes something.

~~~
inglor
A singleton is basically a global variable and those aren't really important
to "shim" in Go. Object method calls are pretty much the same conceptually as
message passing but when you actually need to synchronize as you point out
goroutines and channels make things much simpler. I think what this post was
going for wasn't "use singletons", it was "look at these interesting threading
issues that arise and how we address them in (non idiomatic) Go"

~~~
pcwalton
There's more that needs to be done if the goal is "look at these interesting
threading issues that arise and how we address them in (non idiomatic) Go",
because the initialization described in the post is broken.

Shared-memory multithreading is hard. Golang does not do much to prevent you
from shooting yourself in the foot here, as this post proves. So use the
abstractions wherever possible. In this case, Once correctly performs the
atomics, and naive double-checked locking doesn't.

------
pstuart
This seems more idiomatic:

    
    
      func init() {
          instance = &singleton{}
      }

~~~
Jabbles
If instance can truly be initialized like that, then there's no need for the
init() function, just do it at the top level:

var instance = &singleton{}

In fact, a lot of idiomatic Go will ignore the Get() method, exporting the
instance itself:

var Instance = &singleton{}

Clearly if you overwrite it, bad things will happen. Don't do that.

There may possibly be a problem with unnecessarily slowing startup times in
the case you don't need the singleton and initialization is more complicated
than a malloc - in which case, profiling will tell you and you can revert to
the method in the blog post.

Remember that Go's strict import/dependency requirements mean you're unlikely
to import the package (and trigger the initialization) unless you actually use
the singleton.

It is non-idiomatic to use the sync.atomic package.

~~~
pcwalton
> There may possibly be a problem with unnecessarily slowing startup times in
> the case you don't need the singleton - in which case, profiling will tell
> you and you can revert to the method in the blog post.

Not just in that case. If you lazily initialize then you can get other things
done before—or while—you're waiting for the singleton constructor to run.
Global constructors are suboptimal for performance almost as a rule.

------
dcsommer
There's a package for this, if anyone needs this pattern off the shelf:
[https://github.com/dropbox/godropbox/tree/master/singleton](https://github.com/dropbox/godropbox/tree/master/singleton)

------
Amiga64
Isn't Singleton's really an anti-pattern? SO discussions here:
[http://stackoverflow.com/questions/137975/what-is-so-bad-
abo...](http://stackoverflow.com/questions/137975/what-is-so-bad-about-
singletons)

------
Locke1689
Two things:

1) Unless you've explicitly checked that Go's memory model prevents read/write
moves to allow double-checked locking, don't do it.

2) The pattern is usually a CAS after the check.

------
amelius
Why not use an atomic compare-and-swap instruction as offered by all of the
major underlying hardware architectures?

------
mostafah
Oh no.

