Construcción de APIs REST en Go: Guía completa
Construye APIs REST listas para producción con el sólido ecosistema de Go
Construir APIs REST de alto rendimiento con Go se ha convertido en un enfoque estándar para impulsar sistemas en Google, Uber, Dropbox e innumerables startups.
La simplicidad de Go, su sólido soporte para concurrencia y su compilación rápida lo hacen ideal para microservicios y desarrollo de backend.
Esta impresionante imagen es generada por FLUX.1-Kontext-dev: Modelo de IA para aumentación de imágenes.
¿Por qué Go para el desarrollo de APIs?
Go ofrece varias ventajas convincentes para el desarrollo de APIs:
Rendimiento y Eficiencia: Go se compila a código máquina nativo, ofreciendo un rendimiento cercano al de C sin su complejidad. Su eficiente gestión de memoria y sus tamaños de binarios pequeños lo hacen perfecto para despliegues en contenedores.
Concurrencia Integrada: Las goroutines y los canales hacen que manejar miles de solicitudes concurrentes sea sencillo. Puedes procesar múltiples llamadas a APIs simultáneamente sin un código de subhilos complejo.
Fuerte Biblioteca Estándar: El paquete net/http proporciona un servidor HTTP listo para producción desde el inicio. Puedes construir APIs completas sin ninguna dependencia externa.
Compilación Rápida: La velocidad de compilación de Go permite una iteración rápida durante el desarrollo. Los proyectos grandes se compilan en segundos, no en minutos.
Tipado Estático con Simplicidad: El sistema de tipos de Go detecta errores en tiempo de compilación manteniendo la claridad del código. El lenguaje tiene un conjunto de características pequeño que es rápido de aprender.
Enfoques para construir APIs en Go
Usando la Biblioteca Estándar
La biblioteca estándar de Go proporciona todo lo necesario para el desarrollo básico de APIs. Aquí hay un ejemplo mínimo:
package main
import (
"encoding/json"
"log"
"net/http"
)
type Response struct {
Message string `json:"message"`
Status int `json:"status"`
}
func healthHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(Response{
Message: "API is healthy",
Status: 200,
})
}
func main() {
http.HandleFunc("/health", healthHandler)
log.Println("Server starting on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
Este enfoque ofrece control total y cero dependencias. Es ideal para APIs simples o cuando deseas comprender el manejo de HTTP a nivel fundamental.
Frameworks Populares de Go para Web
Si bien la biblioteca estándar es poderosa, los frameworks pueden acelerar el desarrollo:
Gin: El framework web de Go más popular, conocido por su rendimiento y facilidad de uso. Proporciona enrutamiento conveniente, soporte para middleware y validación de solicitudes.
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.GET("/users/:id", func(c *gin.Context) {
id := c.Param("id")
c.JSON(http.StatusOK, gin.H{
"user_id": id,
"name": "John Doe",
})
})
r.Run(":8080")
}
Chi: Un enrutador ligero e idiomático que se siente como una extensión de la biblioteca estándar. Es especialmente bueno para construir servicios RESTful con enrutamiento anidado.
Echo: Framework de alto rendimiento con un amplio middleware y excelente documentación. Está optimizado para la velocidad manteniendo la facilidad de uso para el desarrollador.
Fiber: Inspirado en Express.js, construido sobre Fasthttp. Es la opción más rápida, pero usa una implementación de HTTP diferente a la de la biblioteca estándar.
Para números con benchmarks, las compensaciones de compatibilidad con fasthttp y una tabla de decisión entre los cinco stacks, consulta Frameworks Web de Go en 2026: net/http, chi, Gin, Echo, Fiber comparados.
Patrones de Arquitectura
Al trabajar con operaciones de base de datos en Go, deberás considerar tu estrategia de ORM. Diferentes proyectos han comparado enfoques como GORM, Ent, Bun y sqlc, cada uno ofrece diferentes compensaciones entre la productividad del desarrollador y el rendimiento.
Arquitectura por Capas
Estructura tu API con una separación clara de preocupaciones:
// Handler Layer - HTTP concerns
type UserHandler struct {
service *UserService
}
func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
user, err := h.service.GetByID(r.Context(), id)
if err != nil {
respondError(w, err)
return
}
respondJSON(w, user)
}
// Service Layer - Business logic
type UserService struct {
repo *UserRepository
}
func (s *UserService) GetByID(ctx context.Context, id string) (*User, error) {
// Validate, transform, apply business rules
return s.repo.FindByID(ctx, id)
}
// Repository Layer - Data access
type UserRepository struct {
db *sql.DB
}
func (r *UserRepository) FindByID(ctx context.Context, id string) (*User, error) {
// Database query implementation
}
Esta separación facilita la prueba y mantiene tu código mantenible a medida que el proyecto crece.
Diseño Dirigido por Dominio
Para aplicaciones complejas, considera organizar el código por dominio en lugar de por capas técnicas. Cada paquete de dominio contiene sus propios modelos, servicios y repositorios.
Si estás construyendo aplicaciones multi-inquilino (multi-tenant), entender los patrones de base de datos para multi-tenancy se vuelve crucial para tu arquitectura de API.
Manejo de Solicitudes y Validación
Validación de Entrada
Valida siempre los datos entrantes antes de procesarlos:
type CreateUserRequest struct {
Email string `json:"email" validate:"required,email"`
Username string `json:"username" validate:"required,min=3,max=50"`
Age int `json:"age" validate:"gte=0,lte=150"`
}
func (h *UserHandler) CreateUser(w http.ResponseWriter, r *http.Request) {
var req CreateUserRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
respondError(w, NewBadRequestError("Invalid JSON"))
return
}
validate := validator.New()
if err := validate.Struct(req); err != nil {
respondError(w, NewValidationError(err))
return
}
// Process valid request
}
El paquete go-playground/validator proporciona reglas de validación extensas y validadores personalizados.
Contexto de Solicitud
Usa context para valores con ámbito de solicitud y cancelación:
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
userID, err := validateToken(token)
if err != nil {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
ctx := context.WithValue(r.Context(), "userID", userID)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
Para un análisis detallado sobre las mejores prácticas de context — incluyendo claves tipadas, propagación de cancelación, presupuestos de tiempo de espera y apagado elegante — consulta Go context.Context Hecho Correctamente.
Autenticación y Seguridad
Autenticación Basada en JWT
Los JSON Web Tokens proporcionan autenticación sin estado:
import "github.com/golang-jwt/jwt/v5"
func generateToken(userID string) (string, error) {
claims := jwt.MapClaims{
"user_id": userID,
"exp": time.Now().Add(time.Hour * 24).Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(os.Getenv("JWT_SECRET")))
}
func validateToken(tokenString string) (string, error) {
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return []byte(os.Getenv("JWT_SECRET")), nil
})
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
return claims["user_id"].(string), nil
}
return "", err
}
Patrones de Middleware
Implementa preocupaciones transversales como middleware:
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
log.Printf("Started %s %s", r.Method, r.URL.Path)
next.ServeHTTP(w, r)
log.Printf("Completed in %v", time.Since(start))
})
}
func rateLimitMiddleware(next http.Handler) http.Handler {
limiter := rate.NewLimiter(10, 20) // 10 requests/sec, burst of 20
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !limiter.Allow() {
http.Error(w, "Rate limit exceeded", http.StatusTooManyRequests)
return
}
next.ServeHTTP(w, r)
})
}
Manejo de Errores
Implementa respuestas de error consistentes:
type APIError struct {
Code int `json:"code"`
Message string `json:"message"`
Details string `json:"details,omitempty"`
}
func (e *APIError) Error() string {
return e.Message
}
func NewBadRequestError(message string) *APIError {
return &APIError{
Code: http.StatusBadRequest,
Message: message,
}
}
func NewNotFoundError(resource string) *APIError {
return &APIError{
Code: http.StatusNotFound,
Message: fmt.Sprintf("%s not found", resource),
}
}
func respondError(w http.ResponseWriter, err error) {
apiErr, ok := err.(*APIError)
if !ok {
apiErr = &APIError{
Code: http.StatusInternalServerError,
Message: "Internal server error",
}
// Log the actual error for debugging
log.Printf("Unexpected error: %v", err)
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(apiErr.Code)
json.NewEncoder(w).Encode(apiErr)
}
Para una mirada más profunda a la arquitectura de errores a través de las capas de repositorio, servicio y handler — incluyendo errores centinela, tipos de error personalizados, traducción en límites y mapeo seguro de respuestas — consulta Arquitectura de Manejo de Errores en Go: Límites y Patrones.
Integración de Base de Datos
Gestión de Conexiones
Usa el agrupamiento de conexiones (connection pooling) para un acceso eficiente a la base de datos:
func initDB() (*sql.DB, error) {
db, err := sql.Open("postgres", os.Getenv("DATABASE_URL"))
if err != nil {
return nil, err
}
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(5 * time.Minute)
return db, db.Ping()
}
Patrones de Consultas
Usa sentencias preparadas y context para operaciones seguras de base de datos:
func (r *UserRepository) FindByEmail(ctx context.Context, email string) (*User, error) {
query := `SELECT id, email, username, created_at FROM users WHERE email = $1`
var user User
err := r.db.QueryRowContext(ctx, query, email).Scan(
&user.ID,
&user.Email,
&user.Username,
&user.CreatedAt,
)
if err == sql.ErrNoRows {
return nil, ErrUserNotFound
}
return &user, err
}
Estrategias de Pruebas
Pruebas de Handlers
Prueba los handlers HTTP usando httptest:
func TestGetUserHandler(t *testing.T) {
// Setup
mockService := &MockUserService{
GetByIDFunc: func(ctx context.Context, id string) (*User, error) {
return &User{ID: "1", Username: "testuser"}, nil
},
}
handler := &UserHandler{service: mockService}
// Execute
req := httptest.NewRequest("GET", "/users/1", nil)
w := httptest.NewRecorder()
handler.GetUser(w, req)
// Assert
assert.Equal(t, http.StatusOK, w.Code)
var response User
json.Unmarshal(w.Body.Bytes(), &response)
assert.Equal(t, "testuser", response.Username)
}
Pruebas de Integración
Prueba flujos completos con una base de datos de pruebas:
func TestCreateUserEndToEnd(t *testing.T) {
// Setup test database
db := setupTestDB(t)
defer db.Close()
// Start test server
server := setupTestServer(db)
defer server.Close()
// Make request
body := strings.NewReader(`{"email":"test@example.com","username":"testuser"}`)
resp, err := http.Post(server.URL+"/users", "application/json", body)
require.NoError(t, err)
defer resp.Body.Close()
// Verify response
assert.Equal(t, http.StatusCreated, resp.StatusCode)
// Verify database state
var count int
db.QueryRow("SELECT COUNT(*) FROM users WHERE email = $1", "test@example.com").Scan(&count)
assert.Equal(t, 1, count)
}
Documentación de API
OpenAPI/Swagger
Documenta tu API usando especificaciones OpenAPI:
// @title User API
// @version 1.0
// @description API for managing users
// @host localhost:8080
// @BasePath /api/v1
// @Summary Get user by ID
// @Description Retrieves a user's information by their ID
// @Tags users
// @Accept json
// @Produce json
// @Param id path string true "User ID"
// @Success 200 {object} User
// @Failure 404 {object} APIError
// @Router /users/{id} [get]
func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) {
// Implementation
}
Usa swaggo/swag para generar documentación de API interactiva a partir de estos comentarios.
Optimización de Rendimiento
Compresión de Respuestas
Habilita la compresión gzip para las respuestas:
import "github.com/NYTimes/gziphandler"
func main() {
r := chi.NewRouter()
r.Use(gziphandler.GzipHandler)
// Rest of setup
}
Caché
Implementa el caché para datos accedidos con frecuencia:
import "github.com/go-redis/redis/v8"
type CachedUserRepository struct {
repo *UserRepository
cache *redis.Client
}
func (r *CachedUserRepository) GetByID(ctx context.Context, id string) (*User, error) {
// Try cache first
cached, err := r.cache.Get(ctx, "user:"+id).Result()
if err == nil {
var user User
json.Unmarshal([]byte(cached), &user)
return &user, nil
}
// Cache miss - fetch from database
user, err := r.repo.FindByID(ctx, id)
if err != nil {
return nil, err
}
// Store in cache
data, _ := json.Marshal(user)
r.cache.Set(ctx, "user:"+id, data, 10*time.Minute)
return user, nil
}
Agrupamiento de Conexiones
Reutiliza las conexiones HTTP para llamadas a APIs externas:
var httpClient = &http.Client{
Timeout: 10 * time.Second,
Transport: &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 10,
IdleConnTimeout: 90 * time.Second,
},
}
Consideraciones de Despliegue
Contenerización con Docker
Crea imágenes Docker eficientes usando construcciones de múltiples etapas:
# Build stage
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o api ./cmd/api
# Production stage
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/api .
EXPOSE 8080
CMD ["./api"]
Esto produce una imagen mínima (típicamente menos de 20MB) con solo tu binario y los certificados esenciales.
Gestión de Configuración
Usa variables de entorno y archivos de configuración:
type Config struct {
Port string
DatabaseURL string
JWTSecret string
LogLevel string
}
func LoadConfig() (*Config, error) {
return &Config{
Port: getEnv("PORT", "8080"),
DatabaseURL: getEnv("DATABASE_URL", ""),
JWTSecret: getEnv("JWT_SECRET", ""),
LogLevel: getEnv("LOG_LEVEL", "info"),
}, nil
}
func getEnv(key, defaultValue string) string {
if value := os.Getenv(key); value != "" {
return value
}
return defaultValue
}
Apagado Elegante
Maneja las señales de apagado correctamente:
func main() {
server := &http.Server{
Addr: ":8080",
Handler: setupRouter(),
}
// Start server in goroutine
go func() {
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("Server error: %v", err)
}
}()
// Wait for interrupt signal
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Println("Shutting down server...")
// Give outstanding requests 30 seconds to complete
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
log.Fatalf("Server forced to shutdown: %v", err)
}
log.Println("Server exited")
}
Monitoreo y Observabilidad
Registro Estructurado
Usa el registro estructurado para una mejor buscabilidad:
import "go.uber.org/zap"
func setupLogger() (*zap.Logger, error) {
config := zap.NewProductionConfig()
config.OutputPaths = []string{"stdout"}
return config.Build()
}
func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) {
logger := h.logger.With(
zap.String("method", r.Method),
zap.String("path", r.URL.Path),
zap.String("user_id", r.Context().Value("userID").(string)),
)
logger.Info("Processing request")
// Handler logic
}
Zap es una elección sólida cuando deseas un registrador de terceros maduro. Si prefieres la biblioteca estándar, log/slog (Go 1.21+) ofrece registros amigables con JSON, supresión a nivel de handler y campos que se alinean con trazas y pipelines de registro. Consulta Registro Estructurado en Go con slog para Observabilidad y Alertas.
Recolección de Métricas
Expón métricas de Prometheus:
import "github.com/prometheus/client_golang/prometheus"
var (
requestDuration = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "http_request_duration_seconds",
Help: "Duration of HTTP requests",
},
[]string{"method", "path", "status"},
)
)
func init() {
prometheus.MustRegister(requestDuration)
}
func metricsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
recorder := &statusRecorder{ResponseWriter: w, status: 200}
next.ServeHTTP(recorder, r)
duration := time.Since(start).Seconds()
requestDuration.WithLabelValues(
r.Method,
r.URL.Path,
strconv.Itoa(recorder.status),
).Observe(duration)
})
}
Patrones Avanzados
Trabajo con Salida Estructurada
Al construir APIs que se integran con LLMs, podrías necesitar restringir las respuestas con salida estructurada. Esto es particularmente útil para funciones impulsadas por IA en tu API.
Rastreo Web para Fuentes de Datos de API
Si tu API necesita agregar datos de otros sitios web, entender las alternativas a Beautiful Soup en Go puede ayudarte a implementar funcionalidades de rastreo web robustas.
Generación de Documentos
Muchas APIs necesitan generar documentos. Para la generación de PDF en Go, hay varias librerías y enfoques que puedes integrar en tus puntos finales de API.
Búsqueda Semántica y Reclasificación
Para APIs que tratan con búsqueda y recuperación de texto, implementar reclasificación con modelos de embedding puede mejorar significativamente la relevancia de los resultados de búsqueda.
Construcción de Servidores MCP
Si estás implementando APIs que siguen el Protocolo de Contexto del Modelo (Model Context Protocol), echa un vistazo a esta guía sobre implementación de servidores MCP en Go., que cubre especificaciones del protocolo e implementaciones prácticas.
Errores Comunes y Soluciones
No Usar Contextos Correctamente
Pasa y respeta siempre el context a lo largo de tu cadena de llamadas. Esto habilita una cancelación y un manejo de timeouts adecuado.
Ignorar Fugas de Goroutines
Asegúrate de que todas las goroutines puedan terminar. Usa contextos con plazos y siempre ten una forma de señalar la finalización.
Mal Manejo de Errores
No devuelvas errores crudos de la base de datos a los clientes. Envuelve los errores con contexto y devuelve mensajes saneados en las respuestas de la API.
Falta de Validación de Entrada
Valida todas las entradas en el punto de entrada. Nunca confíes en los datos del cliente, incluso de usuarios autenticados.
Pruebas Inadecuadas
No solo pruebes el camino feliz. Cubre casos de error, condiciones extremas y escenarios de acceso concurrente.
Resumen de Buenas Prácticas
-
Comienza Simple: Empieza con la biblioteca estándar. Agrega frameworks cuando la complejidad lo demande.
-
Capa tu Aplicación: Separa los handlers HTTP, la lógica de negocio y el acceso a datos por mantenibilidad.
-
Valida Todo: Revisa las entradas en los límites. Usa tipado fuerte y librerías de validación.
-
Maneja Errores de Manera Consistente: Devuelve respuestas de error estructuradas. Registra errores internos pero no los expongas.
-
Usa Middleware: Implementa preocupaciones transversales (autenticación, registro, métricas) como middleware.
-
Prueba a Fondo: Escribe pruebas unitarias para la lógica, pruebas de integración para el acceso a datos y pruebas de extremo a extremo para los flujos.
-
Documenta tu API: Usa OpenAPI/Swagger para documentación interactiva.
-
Monitorea Producción: Implementa registro estructurado, recopilación de métricas y comprobaciones de salud.
-
Optimiza Cuidadosamente: Perfilamos antes de optimizar. Usa caché, agrupamiento de conexiones y compresión donde sea beneficioso.
-
Diseña para el Apagado Elegante: Maneja las señales de terminación y drena las conexiones correctamente.
Lista de Verificación para Comenzar
Para referencia al trabajar en proyectos de Go, tener una hoja de referencia completa de Go a mano puede acelerar el desarrollo y servir como referencia rápida para la sintaxis y los patrones comunes.
¿Listo para construir tu primera API en Go? Comienza con estos pasos:
- ✅ Configura tu entorno de Go y la estructura del proyecto
- ✅ Elige entre la biblioteca estándar o un framework
- ✅ Implementa puntos finales CRUD básicos
- ✅ Añade validación de solicitudes y manejo de errores
- ✅ Implementa middleware de autenticación
- ✅ Añade integración de base de datos con agrupamiento de conexiones
- ✅ Escribe pruebas unitarias y de integración
- ✅ Añade documentación de API
- ✅ Implementa registro y métricas
- ✅ Conteneriza con Docker
- ✅ Configura la pipeline de CI/CD
- ✅ Despliega a producción con monitoreo
Conclusión
Go proporciona una excelente base para construir APIs REST, combinando rendimiento, simplicidad y herramientas robustas. Ya estés construyendo microservicios, herramientas internas o APIs públicas, el ecosistema de Go tiene soluciones maduras para cada requisito.
La clave del éxito es comenzar con patrones de arquitectura sólidos, implementar un manejo de errores y validación adecuados desde el principio, y construir una cobertura de pruebas exhaustiva. A medida que tu API crezca, las características de rendimiento de Go y su sólido soporte para concurrencia te servirán bien.
Recuerda que el desarrollo de APIs es iterativo. Comienza con una implementación mínima viable, reúne retroalimentación y refiná tu enfoque basándote en patrones de uso en el mundo real. La compilación rápida de Go y sus refactorizaciones sencillas hacen que este ciclo de iteración sea fluido y productivo.
Enlaces Útiles
- Hoja de Referencia de Go
- Registro Estructurado en Go con slog para Observabilidad y Alertas
- Comparando ORMs de Go para PostgreSQL: GORM vs Ent vs Bun vs sqlc
- Patrones de Base de Datos para Multi-Tenancy con ejemplos en Go
- Alternativas a Beautiful Soup para Go
- Generación de PDF en GO - Librerías y ejemplos
- Restringir LLMs con Salida Estructurada: Ollama, Qwen3 & Python o Go
- Reclasificación de documentos de texto con Ollama y el modelo de embedding Qwen3 - en Go
- Protocolo de Contexto del Modelo (MCP), y notas sobre la implementación de servidores MCP en Go
Recursos Externos
Documentación Oficial
- Documentación Oficial de Go - La documentación y tutoriales oficiales de Go
- Paquete net/http de Go - Documentación del paquete HTTP de la biblioteca estándar
- Effective Go - Buenas prácticas para escribir código Go claro e idiomático
Frameworks y Librerías Populares
- Framework Web Gin - Framework web HTTP rápido con funciones extensas
- Enrutador Chi - Enrutador ligero e idiomático para construir servicios HTTP en Go
- Framework Echo - Framework web de alto rendimiento, extensible y minimalista
- Framework Fiber - Framework web inspirado en Express construido sobre Fasthttp
- GORM - La fantástica librería ORM para Golang
- golang-jwt - Implementación de JWT para Go
Herramientas de Pruebas y Desarrollo
- Testify - Un conjunto de herramientas con aserciones comunes y mocks
- Paquete httptest - Utilidades de la biblioteca estándar para pruebas HTTP
- Swaggo - Genera automáticamente documentación de APIs RESTful
- Air - Recarga en vivo para aplicaciones Go durante el desarrollo
Buenas Prácticas y Guías
- Estructura de Proyectos Go - Estructuras estándar de proyectos Go
- Guía de Estilo Go de Uber - Guía de estilo Go completa de Uber
- Comentarios de Revisión de Código Go - Comentarios comunes hechos durante las revisiones de código Go
- Buenas Prácticas de Diseño de APIs REST - Principios generales de diseño de APIs REST
Seguridad y Autenticación
- Prácticas de Codificación Segura en Go de OWASP - Pautas de seguridad para aplicaciones Go
- OAuth2 para Go - Implementación de OAuth 2.0
- Paquete bcrypt - Implementación de hash de contraseñas
Rendimiento y Monitoreo
- pprof - Herramienta de perfilado integrada para programas Go
- Cliente de Prometheus - Librería de instrumentación de Prometheus para Go
- Registrador Zap - Registro estructurado, rápido y por niveles
- Centro de Arquitectura de Aplicaciones — Diseño de API, estructura de código y patrones de integración