Enterprise Go: cómo escribir código que no dé vergüenza mostrar al CTO

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

Go en los grandes negocios: por qué ya no es solo un "lenguaje para microservicios"

\n\n

Cuando escuchas "Enterprise Go", ¿qué te viene a la mente? ¿Aburridas normativas corporativas? ¿Interminables revisiones de código? ¿O quizás la sensación de que Go es solo para startups y DevOps?

\n\n

En realidad, Go en la empresa es un nivel completamente diferente de disciplina y cultura de ingeniería. En grandes compañías (Uber, Dropbox, Salesforce, Twitch) no solo escriben microservicios en Go, sino plataformas enteras que procesan millones de solicitudes por segundo. Y aquí, "simplemente funciona" no es suficiente.

\n\n

En este artículo, analizaremos las características clave del desarrollo en Go en la empresa: desde el diseño de paquetes hasta el registro en producción. Habrá mucho código y mínimo contenido superfluo.

\n\n

1. Arquitectura: no repitas el error del "monolito en microservicios"

\n\n

El problema más común que veo en proyectos Go de nivel empresarial es el intento de trasladar la arquitectura estilo Java a Go. El resultado: cientos de interfaces innecesarias y capas de abstracción que solo ralentizan el desarrollo.

\n\n

Regla "Paquete por funcionalidad, no por capa"

\n\n

En lugar de crear carpetas /models, /handlers, /services — agrupa por dominios de negocio:

\n\n
miapp/\n├── cmd/\n│   └── server/\n│       └── main.go\n├── internal/\n│   ├── user/          # Todo lo relacionado con usuarios\n│   │   ├── handler.go\n│   │   ├── service.go\n│   │   ├── repository.go\n│   │   └── user.go    # Modelo de datos\n│   ├── payment/       # Todo lo relacionado con pagos\n│   │   ├── handler.go\n│   │   ├── service.go\n│   │   ├── gateway.go\n│   │   └── payment.go\n│   └── pkg/           # Utilidades comunes\n└── go.mod
\n\n

Este enfoque es una de las mejores prácticas de Go para la empresa. Reduce el acoplamiento y hace que el código sea predecible. Cuando un nuevo desarrollador abre el proyecto, ve inmediatamente la lógica de negocio, no capas de abstracción.

\n\n

Interfaces: acepta interfaces, devuelve estructuras

\n\n

Este es un consejo clásico de la comunidad Go, pero en la empresa es crítico. Las interfaces deben ser pequeñas (1-2 métodos) y definirse donde se usan, no donde se implementan.

\n\n
// MAL: la interfaz se define junto a la implementación\npackage user\n\ntype UserRepository interface {\n    FindByID(id string) (*User, error)\n    Save(user *User) error\n}\n\ntype postgresRepo struct { ... }\n\n// BIEN: la interfaz está donde se necesita\npackage user\n\ntype Storage interface {\n    Get(id string) (*User, error)\n    Put(user *User) error\n}\n\ntype service struct {\n    db Storage\n}\n\nfunc NewService(db Storage) *service {\n    return &service{db: db}\n}
\n\n

¿Por qué es importante? Porque en la empresa a menudo cambias de backend (PostgreSQL -> CockroachDB, Redis -> KeyDB). Las interfaces definidas del lado del consumidor permiten hacerlo sin dolor.

\n\n

2. Manejo de errores: deja de ignorar _

\n\n

Go no tiene excepciones, y eso es genial. Pero en proyectos empresariales, los errores no son solo if err != nil. Es toda una cultura.

\n\n

¿Envolver o no envolver?

\n\n

Usa fmt.Errorf con %w para crear cadenas de errores. Esto permite conservar la pila de llamadas y simplifica la depuración.

\n\n
func (s *service) ProcessOrder(ctx context.Context, orderID string) error {\n    order, err := s.orderRepo.Get(ctx, orderID)\n    if err != nil {\n        return fmt.Errorf("obteniendo pedido %s: %w", orderID, err)\n    }\n\n    if err := s.paymentGateway.Charge(ctx, order.Amount); err != nil {\n        return fmt.Errorf("cobrando pedido %s: %w", orderID, err)\n    }\n\n    return nil\n}
\n\n

En el nivel superior (en handler/middleware) usa errors.Is() y errors.As() para verificar tipos de errores:

\n\n
if errors.Is(err, ErrNotFo                

Blogs

Book Recommendations