1. O que é o Padrão Singleton

O Padrão Singleton é um padrão de design de criação que garante que uma classe tenha apenas uma instância e fornece um ponto de acesso global a essa instância para recuperação. O padrão Singleton é comumente usado em cenários onde os recursos precisam ser compartilhados ou o acesso a uma instância específica precisa ser controlado.

2. Características e Vantagens do Padrão Singleton

O Padrão Singleton possui as seguintes características e vantagens:

  • Garante que a classe tenha apenas um objeto de instância
  • Fornece um ponto de acesso global para que o código externo obtenha a instância
  • Evita a criação repetida de instâncias, economizando recursos do sistema

3. Cenários de Aplicação do Padrão Singleton

O Padrão Singleton é adequado para os seguintes cenários de aplicação:

  • Registros: Garantindo que haja apenas um registro para todo o sistema para evitar registros duplicados.
  • Pool de Conexão de Banco de Dados: Em ambientes de alta concorrência, a utilização do Padrão Singleton pode evitar a criação e destruição frequentes de conexões de banco de dados.

4. Implementação do Padrão Singleton em Golang

Em Golang, existem diferentes maneiras de implementar o Padrão Singleton. Abaixo estão dois métodos de implementação comuns.

4.1. Implementação usando Inicialização Preguiçosa e Inicialização Apressada

A inicialização preguiçosa cria o objeto de instância quando é usado pela primeira vez, enquanto a inicialização apressada cria o objeto de instância quando o programa inicia.

// Implementação do Padrão Singleton com inicialização preguiçosa
package singleton

type Singleton struct {
}

var instance *Singleton

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

// Implementação do Padrão Singleton com inicialização apressada
package singleton

type Singleton struct {
}

var instance *Singleton = &Singleton{}

func GetInstance() *Singleton {
    return instance
}

4.2. Problemas de Segurança de Thread no Padrão Singleton

O método de implementação de inicialização preguiçosa acima pode apresentar problemas em um ambiente multithread, pois vários threads podem entrar simultaneamente na condição if instance == nil, levando à criação de múltiplas instâncias.

4.3. Implementando o Padrão Singleton Seguro para Thread usando sync.Once

Usando sync.Once, garante-se que apenas uma gorrotina execute o código de inicialização, resolvendo assim o problema de segurança de thread.

// Implementando o Padrão Singleton seguro para thread 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. Implementando o Padrão Singleton de Inicialização Preguiçosa Seguro para Thread usando sync.Mutex

Outra maneira de implementar um Padrão Singleton seguro para thread com inicialização preguiçosa é usar sync.Mutex para travar e garantir que apenas uma gorrotina execute a operação de inicialização.

// Implementando o Padrão Singleton de Inicialização Preguiçosa Seguro para Thread 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
}