install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/TerminalSkills/skills/gin" ~/.claude/skills/comeonoliver-skillshub-gin && rm -rf "$T"
manifest:
skills/TerminalSkills/skills/gin/SKILL.mdsource 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
- Binding for validation — Use
with struct tags (ShouldBindJSON
); rejects bad input before handlerbinding:"required,email" - Route groups — Group routes by prefix and middleware:
api := r.Group("/api", authMiddleware()) - Error handling — Return consistent error JSON; use custom error types for business logic errors
- Middleware chain — Use
to continue,c.Next()
to stop; middleware runs in orderc.Abort() - Context values — Store auth user with
; retrieve withc.Set("user", user)
in handlersc.Get("user") - gin.H for quick JSON — Use
for ad-hoc responses; use structs for typed, documented responsesgin.H{} - Graceful shutdown — Handle SIGTERM; drain connections before exit for zero-downtime deploys
- Release mode — Set
in production; disables debug logging, improves performanceGIN_MODE=release