Padrões de Projeto em Go (Golang) com Exemplos de Código
Padrões de projeto são soluções comprovadas para problemas típicos de desenvolvimento. Em Go, com sua sintaxe concisa e ausência de POO clássico, muitos padrões ganham uma implementação única. Neste artigo, vamos explorar três grupos de padrões: criacionais, estruturais e comportamentais — com exemplos práticos em Golang.
O material será útil tanto para iniciantes quanto para desenvolvedores Go experientes que buscam escrever código limpo, reutilizável e testável.
1. Padrões Criacionais (Creational Patterns)
Os padrões criacionais gerenciam o processo de criação de objetos. Em Go, onde não há construtores nem herança, sua implementação é especialmente elegante.
1.1. Singleton
Garante que um tipo tenha apenas uma instância e fornece um ponto de acesso global a ela. Em Go, é frequentemente implementado com sync.Once.
package singleton
import ( "sync")
type Database struct { connection string}
var ( instance *Database once sync.Once)
func GetDatabase() *Database { once.Do(func() { instance = &Database{connection: "postgres://user:pass@localhost/db"} }) return instance}Quando usar: trabalho com pool de conexões, cache, logger.
1.2. Factory Method
Define uma interface para criar um objeto, mas permite que subclasses alterem o tipo do objeto criado. Em Go, o Factory Method é simplesmente uma função que retorna uma interface.
package factory
import "fmt"
// Product interfacetype INotification interface { Send(message string) string}
// Concrete productstype Email struct{}
func (e *Email) Send(msg string) string { return fmt.Sprintf("Email sent: %s", msg)}
type SMS struct{}
func (s *SMS) Send(msg string) string { return fmt.Sprintf("SMS sent: %s", msg)}
// Factory functionfunc CreateNotification(notifType string) INotification { switch notifType { case "email": return &Email{} case "sms": return &SMS{} default: return nil }}Quando usar: quando o tipo do objeto a ser criado não é conhecido antecipadamente.
1.3. Builder
Separa a construção de um objeto complexo de sua representação. Em Go, o Builder é uma struct com métodos setters que retornam a própria struct para chamadas encadeadas.
package builder
type Pizza struct { Size string Cheese bool Pepperoni bool}
type PizzaBuilder struct { pizza Pizza}
func NewPizzaBuilder() *PizzaBuilder { return &PizzaBuilder{}}
func (b *PizzaBuilder) SetSize(size string) *PizzaBuilder { b.pizza.Size = size return b}
func (b *PizzaBuilder) AddCheese() *PizzaBuilder { b.pizza.Cheese = true return b}
func (b *PizzaBuilder) AddPepperoni() *PizzaBuilder { b.pizza.Pepperoni = true return b}
func (b *PizzaBuilder) Build() Pizza { return b.pizza}Quando usar: quando o objeto tem muitos parâmetros opcionais.
2. Padrões Estruturais (Structural Patterns)
Os padrões estruturais definem maneiras de compor objetos e classes em estruturas maiores, mantendo flexibilidade e eficiência.
2.1. Adapter
Permite que objetos com interfaces incompatíveis trabalhem juntos. Em Go, isso é feito usando interfaces e structs wrapper.
package adapter
import "fmt"
// Target interfacetype USB interface { ConnectWithUSB() string}
// Adaptee (classe incompatível)type MemoryCard struct{}
func (m *MemoryCard) ReadFromCard() string { return "Data read from memory card"}
// Adaptertype CardReader struct { card *MemoryCard}Quando usar: quando você precisa integrar classes com interfaces incompatíveis.