Skills gin

install
source · Clone the upstream repo
git clone https://github.com/TerminalSkills/skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/TerminalSkills/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/gin" ~/.claude/skills/terminalskills-skills-gin && rm -rf "$T"
manifest: skills/gin/SKILL.md
source content

Gin — High-Performance Go Web Framework

You are an expert in Gin, the fastest Go web framework with a martini-like API. You help developers build high-performance HTTP APIs with routing, middleware, request validation, JSON serialization, error handling, and graceful shutdown — delivering 100K+ requests/second on modest hardware with Go's type safety and concurrency model.

Core Capabilities

Server and Routes

package main

import (
    "net/http"
    "strconv"
    "github.com/gin-gonic/gin"
)

type User struct {
    ID    uint   `json:"id"`
    Name  string `json:"name" binding:"required,min=2,max=100"`
    Email string `json:"email" binding:"required,email"`
    Role  string `json:"role" binding:"oneof=user admin"`
}

func main() {
    r := gin.Default()  // Logger + Recovery middleware

    // Middleware
    r.Use(corsMiddleware())
    r.Use(rateLimiter(100))  // 100 req/s

    api := r.Group("/api")
    api.Use(authMiddleware())
    {
        api.GET("/users", listUsers)
        api.POST("/users", createUser)
        api.GET("/users/:id", getUser)
        api.PUT("/users/:id", updateUser)
        api.DELETE("/users/:id", deleteUser)
    }

    r.Run(":8080")
}

func listUsers(c *gin.Context) {
    page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
    limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20"))

    users, total := db.FindUsers(page, limit)
    c.JSON(http.StatusOK, gin.H{
        "data":  users,
        "total": total,
        "page":  page,
    })
}

func createUser(c *gin.Context) {
    var input User
    if err := c.ShouldBindJSON(&input); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    user, err := db.CreateUser(input)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create user"})
        return
    }
    c.JSON(http.StatusCreated, user)
}

func getUser(c *gin.Context) {
    id := c.Param("id")
    user, err := db.FindUser(id)
    if err != nil {
        c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
        return
    }
    c.JSON(http.StatusOK, user)
}

// Auth middleware
func authMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        token := c.GetHeader("Authorization")
        if token == "" {
            c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "missing token"})
            return
        }
        user, err := validateToken(token)
        if err != nil {
            c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid token"})
            return
        }
        c.Set("user", user)
        c.Next()
    }
}

Graceful Shutdown

func main() {
    r := gin.Default()
    // ... routes

    srv := &http.Server{Addr: ":8080", Handler: r}
    go func() { srv.ListenAndServe() }()

    quit := make(chan os.Signal, 1)
    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
    <-quit

    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    srv.Shutdown(ctx)
}

Installation

go get -u github.com/gin-gonic/gin

Best Practices

  1. Binding for validation — Use
    ShouldBindJSON
    with struct tags (
    binding:"required,email"
    ); rejects bad input before handler
  2. Route groups — Group routes by prefix and middleware:
    api := r.Group("/api", authMiddleware())
  3. Error handling — Return consistent error JSON; use custom error types for business logic errors
  4. Middleware chain — Use
    c.Next()
    to continue,
    c.Abort()
    to stop; middleware runs in order
  5. Context values — Store auth user with
    c.Set("user", user)
    ; retrieve with
    c.Get("user")
    in handlers
  6. gin.H for quick JSON — Use
    gin.H{}
    for ad-hoc responses; use structs for typed, documented responses
  7. Graceful shutdown — Handle SIGTERM; drain connections before exit for zero-downtime deploys
  8. Release mode — Set
    GIN_MODE=release
    in production; disables debug logging, improves performance