Container de Injeção de Dependência para Go (Golang): Wire, Dig e Uber FX
Injeção de Dependência (DI) é um padrão de projeto no qual um objeto recebe suas dependências externamente, em vez de criá-las por si só. Em Go (Golang), a DI é especialmente útil para criar código modular, testável e escalável. As ferramentas de DI mais populares para Go são Google Wire, Uber Dig e Uber FX. Neste artigo, examinaremos cada uma delas, suas características e exemplos de uso.
Por que a Injeção de Dependência é necessária em Go?
Go é uma linguagem estaticamente tipada com passagem explícita de parâmetros. Sem DI, os desenvolvedores frequentemente criam variáveis globais ou fábricas, o que dificulta os testes e a manutenção. Os containers de DI resolvem esses problemas:
- Baixo acoplamento — os componentes dependem de interfaces, não de implementações concretas.
- Testabilidade — é fácil substituir dependências por mocks.
- Simplificação da configuração — o container resolve automaticamente o grafo de dependências.
Google Wire — geração de código em tempo de compilação
Wire da Google não é um container em tempo de execução, mas um gerador de código. Ele analisa funções construtoras e gera código para vincular dependências na fase de compilação. Isso resulta em zero sobrecarga durante a execução e detecção precoce de erros.
Instalação do Wire
go install github.com/google/wire/cmd/wire@latestExemplo de uso do Wire
Suponha que temos um serviço que depende de um banco de dados e um logger:
// main.gopackage main
import "fmt"
type Logger struct{}
func NewLogger() Logger { return Logger{} }
func (l Logger) Log(msg string) { fmt.Println(msg) }
type Database struct { logger Logger}
func NewDatabase(logger Logger) Database { return Database{logger: logger}}
type Service struct { db Database log Logger}
func NewService(db Database, log Logger) Service { return Service{db: db, log: log}}Agora vamos criar o arquivo wire.go com a instrução para o Wire:
// wire.go//go:build wireinject// +build wireinject
package main
import "github.com/google/wire"
func InitializeService() Service { wire.Build(NewLogger, NewDatabase, NewService) return Service{}}Vamos executar a geração:
wireO Wire criará o arquivo wire_gen.go com o código de inicialização pronto:
// wire_gen.go// Code generated by Wire. DO NOT EDIT.
package main
func InitializeService() Service { logger := NewLogger() database := NewDatabase(logger) service := NewService(database, logger) return service}Vantagens do Wire:
- Erros em tempo de compilação.
- Sem reflection, alta performance.
- Código simples e previsível.
Desvantagens do Wire:
- Requer uma etapa separada de geração.
- Difícil de usar com dependências dinâmicas.
Uber Dig — container em tempo de execução com reflection
Dig da Uber é um container que opera em tempo de execução. Ele usa reflection para analisar tipos e resolver automaticamente as dependências. O Dig fornece uma API simples para registrar construtores e extrair objetos.
Instalação do Dig
go get go.uber.org/digExemplo de uso do Dig
package main
import ( "fmt" "go.uber.org/dig")
type Config struct { Port int}
func NewConfig() *Config { return &Config{Port: 8080}}
type Server struct { config *Config}
func NewServer(c *Config) *Server { return &Server{config: c}}
func (s *Server) Start() { fmt.Print Também na biblioteca
Agendador de tarefas PHP: cron-express
Geolocalização e Mapas em C++: Visão Geral de Bibliotecas e Ferramentas
Filas de Tarefas em Swift: GCD, OperationQueue e Swift Concurrency
Registro de Logs para TypeScript: Biblioteca Winston
Aprendizado de Máquina em C# (.NET): Visão Geral de Bibliotecas e Ferramentas