💉 Injeção de Dependência em Go?

Guilherme Henrique - Aug 5 - - Dev Community

Imagine que você está construindo um robô que precisa de uma bateria para funcionar. Em vez de soldar a bateria diretamente no robô, você cria um compartimento para a bateria que pode ser facilmente a trocada. Assim, você pode trocar a bateria quando ela descarregar ou usar diferentes tipos de bateria, sem precisar modificar o robô inteiro.

Ou agora imagine que você tem um restaurante e precisa de um fornecedor de alimentos. Em vez de contratar um fornecedor específico e depender exclusivamente dele, você cria uma lista de requisitos que um bom fornecedor deve atender (qualidade dos produtos, preço, prazo de entrega, etc.).

Assim, você pode facilmente trocar de fornecedor caso o atual não esteja atendendo às suas necessidades ou encontrar um fornecedor melhor, sem precisar mudar todo o funcionamento do seu restaurante.
Na programação, a Injeção de Dependência (DI) funciona de forma semelhante. Em vez de "amarrar" um componente (como um banco de dados) diretamente ao seu código, você cria uma "interface" que define como o componente deve se comportar.

Exemplo prático em Go:

Imagine um programa que precisa armazenar dados. Em vez de escrever o código para acessar um banco de dados específico (como PostgreSQL ou MySQL) diretamente no programa, você cria uma interface IDatabase:

type IDatabase interface {
    Create(data string) error
    FindOne (id int) (entity, error)
}
Enter fullscreen mode Exit fullscreen mode

Depois, você cria diferentes implementações dessa interface, como PostgresAdapter (para armazenar dados em um banco de dados PostgreSQL) ou MongoAdapter (para armazenar dados em um banco NoSQL)

adapter/postgres.go

type PostgresAdapter struct { /* ... */ }

func (s *PostgresAdapter)  Create(data string) error { /* ... */ }
func (s *PostgresAdapter) FindOne (id int) (entity, error) { /* ... */ }
Enter fullscreen mode Exit fullscreen mode

adapter/mongo.go

type MongoAdapter struct { /* ... */ }

func (s *MongoAdapter)  Create(data string) error { /* ... */ }
func (s *MongoAdapter) FindOne (id int) (entity, error) { /* ... */ }
Enter fullscreen mode Exit fullscreen mode

Agora, seu programa principal pode receber qualquer implementação de Storage como dependência:

func main() {
    var database IDatabase
    // ... (lógica para escolher a implementação de Storage)

   database.Create("dados importantes")
    data, _ :=database.FindOne(1)
    // ... (usar os dados carregados)
}
Enter fullscreen mode Exit fullscreen mode

Dessa forma, você pode facilmente trocar a forma como os dados são armazenados, sem precisar modificar o código principal do seu programa. Isso torna seu código mais flexível, testável e fácil de manter.

. . .
Terabox Video Player