Gin: APIs JSON rápidas y enlazado
Gin optimiza las APIs REST con mucho JSON con un router rápido, helpers *gin.Context, y enlazado de structs respaldado por go-playground/validator.
Busca en todas las páginas de la documentación
Gin optimiza las APIs REST con mucho JSON con un router rápido, helpers *gin.Context, y enlazado de structs respaldado por go-playground/validator.
Cambia la portabilidad del manejador stdlib por velocidad y ergonomía cuando la mayoría de los endpoints decodifican JSON, validan la entrada y renderizan respuestas JSON.
Los manejadores de Gin reciben *gin.Context, que expone parámetros, valores de consulta, métodos de enlazado y atajos de respuesta (JSON, XML, File).
Las rutas agrupadas (RouterGroup) reflejan diseños de API versionados.
Las etiquetas de enlazado declaran reglas de validación en la capa de transporte mientras las reglas de negocio permanecen en los servicios.
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
g := gin.New()
g.Use(gin.Recovery())
v1 := g.Group("/api/v1")
v1.POST("/users", createUser)
func createUser(c *gin.Context) {
var in createUserRequest
if err := c.ShouldBindJSON(&in); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(201, in)
}Cuándo usar esto:
package main
import (
"net/http"
"sync"
"github.com/gin-gonic/gin"
)
type createUserRequest struct {
Email string `json:"email" binding:"required,email"`
Name string `json:"name" binding:"required,min=2,max=64"`
}
type user struct {
ID int `json:"id"`
Email string `json:"email"`
Name string `json:"name"`
}
type store struct {
mu sync.Mutex
next int
users map[int]user
}
func (s *store) create(email, name string) user {
s.mu.Lock()
defer s.mu.Unlock()
s.next++
u := user{ID: s.next, Email: email, Name: name}
s.users[u.ID] = u
return u
}
func main() {
gin.SetMode(gin.ReleaseMode)
g := gin.New()
g.Use(gin.Recovery())
g.Use(gin.Logger())
db := &store{users: make(map[int]user)}
api := g.Group("/api/v1")
{
api.GET("/health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "ok"})
})
api.POST("/users", func(c *gin.Context) {
var in createUserRequest
if err := c.ShouldBindJSON(&in); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
u := db.create(in.Email, in.Name)
c.JSON(http.StatusCreated, u)
})
api.GET("/users/:id", func(c *gin.Context) {
id := c.Param("id")
c.JSON(http.StatusOK, gin.H{"id": id})
})
}
g.Run(":8080")
}Lo que esto demuestra:
gin.Default() en producción/api/v1 con prefijo compartido:idc.Next() avanza la cadena dentro del middleware de Gin.ShouldBind* lee el cuerpo una vez y devuelve errores sin escribir códigos de estado automáticamente.binding se mapean a reglas de validación; los validadores personalizados se registran en el motor de enlazado de Gin.| Método | Uso típico | En caso de error |
|---|---|---|
ShouldBindJSON | Cuerpos JSON | Devuelve solo error |
ShouldBindQuery | Parámetros de consulta | Devuelve solo error |
ShouldBindUri | Parámetros de ruta en struct | Devuelve solo error |
BindJSON | Cuerpos JSON | Escribe 400 automáticamente |
Prefiere ShouldBind* en los manejadores para que controles la forma de la respuesta.
c.JSON, c.XML, c.YAML y c.ProtoBuf establecen el tipo de contenido y codifican.
c.AbortWithStatusJSON detiene la cadena de middleware después de los errores (común en middleware de autenticación).
// Prueba la lógica del manejador extrayendo una función pura
func createUserHandler(s *store) gin.HandlerFunc {
return func(c *gin.Context) {
var in createUserRequest
if err := c.ShouldBindJSON(&in); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, s.create(in.Email, in.Name))
}
}Las funciones constructoras que devuelven gin.HandlerFunc mantienen las dependencias explícitas y probables.
BindJSON: BindJSON escribe 400 antes de que puedas personalizar los errores. Solución: usa ShouldBindJSON y mapea los errores a tu formato JSON de problema.gin.Default() en producción: El logger de depuración y las asignaciones adicionales pueden ser indeseables. Solución: gin.New() más el middleware elegido.gin.Mode global: Ejecutar accidentalmente el modo de depuración filtra errores detallados. Solución: establece gin.SetMode(gin.ReleaseMode) en main y prueba las configuraciones.gin.H grandes: Los mapas sin tipo ocultan la deriva del esquema. Solución: usa structs de respuesta para APIs públicas.gin.Context es difícil de portar. Solución: mantén los manejadores delgados; llama a funciones Go puras con tipos de dominio.| Alternativa | Usar cuando | No usar cuando |
|---|---|---|
| Echo | Ergonomía similar con helpers WebSocket integrados | El equipo ya está invertido en plugins de Gin |
| chi + validator | Manejadores stdlib y capas JSON explícitas | Quieres la máxima conveniencia de enlazado |
| stdlib + codegen | APIs OpenAPI-first con tipos generados | Quieres un mínimo de herramientas iniciales |
| Fiber | API similar a Express de Fiber (no stdlib) | Requiere compatibilidad con net/http |
Sí, Gin sigue siendo popular para las APIs JSON de Go; verifica las versiones de los módulos en tiempo de compilación según los pines de tu manifiesto.
Mapea validator.ValidationErrors a mensajes específicos de campo en lugar de devolver err.Error() en bruto a los clientes.
Sí, c.Request.Context() transporta los plazos; pásalo a las llamadas de base de datos y RPC.
Escribe middleware func(c *gin.Context) { ...; c.Next() } en los grupos que necesiten autenticación; llama a c.AbortWithStatusJSON en caso de fallo.
Sí, c.HTML con LoadHTMLGlob; muchas APIs JSON omiten las plantillas, pero las interfaces de administración pueden coexistir.
Usa httptest con gin.CreateTestContext o inicia un router y llama a ServeHTTP en solicitudes grabadas.
c.FormFile y c.MultipartForm manejan las subidas; establece MaxMultipartMemory en el motor para archivos grandes.
api := g.Group("/api", authMiddleware) aplica middleware a las rutas registradas en api solamente.
Sí, g.GET("/health", gin.WrapF(stdHandler)) o gin.WrapH para valores de http.Handler.
Ambos son fuertes; Gin tiene un ecosistema de middleware más grande, Echo documenta prominentemente los patrones de WebSockets y manejo de errores.
Los campos JSON opcionales a menudo usan punteros (*string) para distinguir entre ausente y cadena vacía.
Usa grupos de rutas (/v1, /v2) o middleware de versionado basado en encabezados; los grupos mantienen el middleware aislado por versión.
Versiones de Stack: Esta página fue escrita para Go 1.26.x (GC por defecto de Green Tea, go fix modernizers - verifica el parche en la compilación), chi (última - verifica en la compilación), gin (última - verifica en la compilación), echo (última - verifica en la compilación), google.golang.org/grpc (última - verifica en la compilación), sigs.k8s.io/controller-runtime (última - verifica en la compilación), kubebuilder (última - verifica en la compilación), tinygo (última - verifica los objetivos de la placa en la compilación), wazero (última - verifica en la compilación), y golangci-lint (última - verifica el conjunto de linters en la compilación).
Revisado por Chris St. John·Última actualización: 16 jul 2026