Fundamentos de Arquitectura en Go
10 ejemplos para empezar con Arquitectura - 7 básicos y 3 intermedios.
Busca en todas las páginas de la documentación
10 ejemplos para empezar con Arquitectura - 7 básicos y 3 intermedios.
go version).mkdir archdemo && cd archdemo && go mod init example.com/archdemo.Binarios separados, implementación privada y código de biblioteca pública.
archdemo/
cmd/api/main.go
internal/service/
internal/store/
pkg/api/ # tipos de API compartidos opcionales
cmd/ contiene paquetes main - una carpeta por binario.internal/ oculta la implementación a importadores externos.pkg/ es opcional para bibliotecas que deseas que otros módulos importen.Relacionado: Arquitectura en Go: Interfaces Pequeñas, Dependencias Explícitas - por qué importan los límites
Pasa dependencias explícitamente en lugar de globales.
package service
type Greeter struct {
prefix string
}
func New(prefix string) *Greeter {
return &Greeter{prefix: prefix}
}
func (g *Greeter) Hello(name string) string {
return g.prefix + ", " + name
}New valida las entradas y devuelve una estructura lista.Relacionado: Inyección de Dependencias: wire, dig y Cableado Manual - escalando el cableado más allá del
mainhecho a mano
Define el contrato donde se utiliza.
package handler
import "context"
type Lister interface {
List(ctx context.Context) ([]string, error)
}
type HTTP struct {
svc Lister
}
func New(svc Lister) *HTTP {
return &HTTP{svc: svc}
}Lister tiene un método - fácil de simular en pruebas de manejador.internal/store sin importar HTTP.Traduce HTTP a llamadas de dominio; sin SQL en manejadores.
package handler
import (
"encoding/json"
"net/http"
)
func (h *HTTP) List(w http.ResponseWriter, r *http.Request) {
items, err := h.svc.List(r.Context())
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
_ = json.NewEncoder(w).Encode(items)
}r.Context() para cancelación y plazos.Relacionado: Capas de Manejador-Servicio-Repositorio - flujo completo de tres capas
Las reglas de negocio viven entre HTTP y el almacenamiento.
package service
import (
"context"
"fmt"
)
type Repo interface {
All(ctx context.Context) ([]string, error)
}
type Service struct {
repo Repo
}
func New(repo Repo) *Service {
return &Service{repo: repo}
}
func (s *Service) List(ctx context.Context) ([]string, error) {
items, err := s.repo.All(ctx)
if err != nil {
return nil, fmt.Errorf("list: %w", err)
}
return items, nil
}%w) para observabilidad.List satisface la interfaz Lister del manejador del ejemplo 3.Aísla la persistencia detrás de una API pequeña.
package store
import "context"
type Memory struct {
data []string
}
func (m *Memory) All(ctx context.Context) ([]string, error) {
return append([]string(nil), m.data...), nil
}Conecta tipos concretos solo en cmd/api/main.go.
package main
import (
"log"
"net/http"
"example.com/archdemo/internal/handler"
"example.com/archdemo/internal/service"
"example.com/archdemo/internal/store"
)
func main() {
repo := &store.Memory{data: []string{"alpha", "beta"}}
svc := service.New(repo)
h := handler.New(svc)
mux := http.NewServeMux()
mux.HandleFunc("GET /items", h.List)
log.Fatal(http.ListenAndServe(":8080", mux))
}main es el único lugar que conoce todos los tipos concretos.ServeMux.internal/Los paquetes bajo internal/ no pueden ser importados fuera del árbol padre.
// internal/store/pg.go
package store
// Solo example.com/archdemo/... puede importar este paquete.
type PG struct{}internal.Relacionado: Arquitectura Limpia y Hexagonal en Go - puertos en el borde del dominio
Organiza por capacidad cuando los dominios son claros.
internal/
billing/
service.go
handler.go
postgres.go
shipping/
...
internal/platform/) contienen ayudantes de logging y autenticación.Relacionado: Monolito vs Microservicios en Go - cuándo dividir binarios
Registra por qué elegiste un diseño antes de que el debate se repita.
# ADR 0003: Capas de manejador-servicio-repositorio
## Estado
Aceptado
## Contexto
Nueva API HTTP; el equipo quiere lógica de negocio testeable.
## Decisión
Usar paquetes de manejador / servicio / repositorio con interfaces del consumidor.
## Consecuencias
Más paquetes; cableado explícito en main; pruebas unitarias más fáciles.docs/adr/ o .adr/ en la raíz del repositorio.Relacionado: Registros de Decisiones de Arquitectura para Equipos de Go - decisiones clasificadas para servicios de Go
Versiones de Stack: Esta página fue escrita para Go 1.26.x (Predeterminado GC Green Tea, modernizadores go fix - verificar parche en la compilación), chi (última - verificar en la compilación), gin (última - verificar en la compilación), echo (última - verificar en la compilación), google.golang.org/grpc (última - verificar en la compilación), sigs.k8s.io/controller-runtime (última - verificar en la compilación), kubebuilder (última - verificar en la compilación), tinygo (última - verificar objetivos de placa en la compilación), wazero (última - verificar en la compilación) y golangci-lint (última - verificar conjunto de linters en la compilación).
Revisado por Chris St. John·Última actualización: 18 jul 2026