1. Qué es el Patrón Singleton

El Patrón Singleton es un patrón de diseño creacional que garantiza que una clase tenga solo una instancia y proporciona un punto de acceso global a esa instancia para su recuperación. El patrón Singleton se usa comúnmente en escenarios donde los recursos deben ser compartidos o el acceso a una instancia específica necesita ser controlado.

2. Características y Ventajas del Patrón Singleton

El Patrón Singleton tiene las siguientes características y ventajas:

  • Asegura que la clase tenga solo un objeto de instancia
  • Proporciona un punto de acceso global para que el código externo obtenga la instancia
  • Evita la creación repetida de instancias, ahorrando recursos del sistema

3. Escenarios de Aplicación del Patrón Singleton

El Patrón Singleton es adecuado para los siguientes escenarios de aplicación:

  • Registro de eventos: Asegurar que solo haya un registro de eventos para todo el sistema para evitar el registro duplicado.
  • Grupo de conexiones a base de datos: En entornos con alta concurrencia, el uso del Patrón Singleton puede evitar la creación y destrucción frecuente de conexiones a la base de datos.

4. Implementación del Patrón Singleton en Golang

En Golang, existen diferentes formas de implementar el Patrón Singleton. A continuación se muestran dos métodos de implementación comunes.

4.1. Implementación usando Inicialización Perezosa e Inicialización Temprana

La inicialización perezosa crea el objeto de instancia cuando se usa por primera vez, mientras que la inicialización temprana crea el objeto de instancia cuando el programa comienza.

// Implementación del Patrón Singleton con inicialización perezosa
package singleton

type Singleton struct {
}

var instance *Singleton

func GetInstance() *Singleton {
    if instance == nil {
        instance = &Singleton{}
    }
    return instance
}

// Implementación del Patrón Singleton con inicialización temprana
package singleton

type Singleton struct {
}

var instance *Singleton = &Singleton{}

func GetInstance() *Singleton {
    return instance
}

4.2. Problemas de Seguridad de Hilos en el Patrón Singleton

El método de implementación de inicialización perezosa mencionado anteriormente puede tener problemas en un entorno con múltiples hilos porque varios hilos pueden ingresar simultáneamente a la condición if instance == nil, lo que lleva a la creación de múltiples instancias.

4.3. Implementación del Patrón Singleton Seguro para Hilos usando sync.Once

El uso de sync.Once garantiza que solo una goroutine ejecute el código de inicialización, resolviendo así el problema de seguridad en hilos.

// Implementación del Patrón Singleton seguro para hilos usando sync.Once
package singleton

import (
    "sync"
)

type Singleton struct {
}

var instance *Singleton
var once sync.Once

func GetInstance() *Singleton {
    once.Do(func() {
        instance = &Singleton{}
    })
    return instance
}

4.4. Implementación de la Inicialización Perezosa del Patrón Singleton Seguro para Hilos usando sync.Mutex

Otra forma de implementar la inicialización perezosa segura para hilos del Patrón Singleton es usar sync.Mutex para bloquear y garantizar que solo una goroutine ejecute la operación de inicialización.

// Implementación de la inicialización perezosa del Patrón Singleton seguro para hilos usando sync.Mutex
package singleton

import (
    "sync"
)

type Singleton struct {
}

var instance *Singleton
var mu sync.Mutex

func GetInstance() *Singleton {
    if instance == nil {
        mu.Lock()
        defer mu.Unlock()
        if instance == nil {
            instance = &Singleton{}
        }
    }
    return instance
}