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
}