Implementando singleton con sync.Once

Implementando singleton con sync.Once
Photo by Artem Sapegin / Unsplash

En wikipedia el patrón singleton se define como:

'singleton' o 'instancia única' es un patrón de diseño que permite restringir la creación de objetos pertenecientes a una clase o el valor de un tipo a un único objeto.

El objetivo de este patrón es garantizar que solo exista una instancia de una clase y que dicha instancia sea accesible dentro del sistema.

Para implementar este patrón en Go podemos utilizar sync.Once, esta estructura expone la función Do la cual nos ofrece la posibilidad de ejecutar código solamente una vez y además es thread safe.

El siguiente código muestra como utilizar esta esta estructura e implementar el patrón singleton.

package provider

import (
	"log"
	"sync"
)

type ItemProvider struct {
}

var (
	provider *ItemProvider
	once     sync.Once
)

func NewItemProvider() *ItemProvider {
	once.Do(func() {
		provider = &ItemProvider{}
		log.Print("once.Do")
	})
	return provider
}

Agreguemos el siguiente código dentro de la función main para comprobar el comportamiento del código.

package main

import (
	"log"

	"github.com/singleton/provider"
)

func main() {
	p1 := provider.NewItemProvider()
	log.Print(p1)
	p2 := provider.NewItemProvider()
	log.Print(p2)
	p3 := provider.NewItemProvider()
	log.Print(p3)
	p4 := provider.NewItemProvider()
	log.Print(p4)
}

El código mostrará los siguientes mensajes en la consola y podrás notar que el código dentro de la función Do se ejecutó una sola ocasión.

once.Do
&{}
&{}
&{}
&{}

De esta forma hemos implementado de una forma sencilla el patrón singleton con Go.

Happy coding!

Referencias

wikipedia
sync.Once