Contenedor de Inyección de Dependencias para Go (Golang): Wire, Dig y Uber FX

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Contenedor de Inyección de Dependencias para Go (Golang): Wire, Dig y Uber FX



La Inyección de Dependencias (DI) es un patrón de diseño en el cual un objeto recibe sus dependencias desde el exterior, en lugar de crearlas él mismo. En Go (Golang), la DI es especialmente útil para crear código modular, testeable y escalable. Las herramientas DI más populares para Go son Google Wire, Uber Dig y Uber FX. En este artículo, analizaremos cada una de ellas, sus características y ejemplos de uso.



¿Por qué es necesaria la Inyección de Dependencias en Go?

Go es un lenguaje de tipado estático con paso explícito de parámetros. Sin DI, los desarrolladores suelen crear variables globales o fábricas, lo que complica las pruebas y el mantenimiento. Los contenedores DI resuelven estos problemas:

  • Bajo acoplamiento — los componentes dependen de interfaces, no de implementaciones concretas.
  • Testeabilidad — es fácil reemplazar dependencias con mocks.
  • Simplificación de la configuración — el contenedor resuelve automáticamente el grafo de dependencias.


Google Wire — generación de código en tiempo de compilación

Wire de Google no es un contenedor en tiempo de ejecución, sino un generador de código. Analiza las funciones constructoras y genera código para vincular dependencias en la etapa de compilación. Esto proporciona una carga nula durante la ejecución y una detección temprana de errores.



Instalación de Wire

go install github.com/google/wire/cmd/wire@latest


Ejemplo de uso de Wire

Supongamos que tenemos un servicio que depende de una base de datos y un registrador (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}}

Ahora creemos un archivo wire.go con la instrucción para 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{}}

Ejecutemos la generación:

wire

Wire creará un archivo wire_gen.go con el código de inicialización listo:

// 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}

Ventajas de Wire:

  • Errores en tiempo de compilación.
  • Sin reflection, alto rendimiento.
  • Código simple y predecible.

Desventajas de Wire:

  • Requiere un paso de generación separado.
  • Difícil de usar con dependencias dinámicas.


Uber Dig — contenedor en tiempo de ejecución con reflection

Dig de Uber es un contenedor que funciona en tiempo de ejecución. Utiliza reflection para analizar tipos y resolver dependencias automáticamente. Dig proporciona una API simple para registrar constructores y extraer objetos.



Instalación de Dig

go get go.uber.org/dig


Ejemplo de uso de 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

Recommendations