# Gin Framework

> High-performance Go web framework with martini-like API.

- **Type:** Skill
- **Install:** `agentstack add skill-ngxtm-devkit-gin-framework`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [ngxtm](https://agentstack.voostack.com/s/ngxtm)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [ngxtm](https://github.com/ngxtm)
- **Source:** https://github.com/ngxtm/devkit/tree/main/rules/golang/gin-framework

## Install

```sh
agentstack add skill-ngxtm-devkit-gin-framework
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Gin Framework Standards

## Router Setup

```go
package main

import (
    "github.com/gin-gonic/gin"
)

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

    // Routes
    r.GET("/ping", pingHandler)
    r.POST("/users", createUser)

    // Route groups
    api := r.Group("/api/v1")
    {
        api.GET("/users", listUsers)
        api.GET("/users/:id", getUser)
        api.PUT("/users/:id", updateUser)
        api.DELETE("/users/:id", deleteUser)
    }

    r.Run(":8080")
}
```

## Handlers

```go
// Path parameters
func getUser(c *gin.Context) {
    id := c.Param("id")
    user, err := findUser(id)
    if err != nil {
        c.JSON(404, gin.H{"error": "User not found"})
        return
    }
    c.JSON(200, user)
}

// Query parameters
func listUsers(c *gin.Context) {
    page := c.DefaultQuery("page", "1")
    limit := c.DefaultQuery("limit", "10")
    users := fetchUsers(page, limit)
    c.JSON(200, users)
}

// JSON body binding
type CreateUserRequest struct {
    Name  string `json:"name" binding:"required"`
    Email string `json:"email" binding:"required,email"`
}

func createUser(c *gin.Context) {
    var req CreateUserRequest
    if err := c.ShouldBindJSON(&req); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    user := insertUser(req)
    c.JSON(201, user)
}
```

## Binding & Validation

```go
type LoginRequest struct {
    Username string `json:"username" binding:"required,min=3,max=50"`
    Password string `json:"password" binding:"required,min=8"`
}

// Custom validation
type BookingRequest struct {
    CheckIn  time.Time `json:"check_in" binding:"required"`
    CheckOut time.Time `json:"check_out" binding:"required,gtfield=CheckIn"`
}

// Bind from different sources
c.ShouldBindJSON(&obj)    // JSON body
c.ShouldBindQuery(&obj)   // Query string
c.ShouldBind(&obj)        // Auto-detect
```

## Middleware

```go
// Global middleware
r := gin.New()
r.Use(gin.Logger())
r.Use(gin.Recovery())
r.Use(corsMiddleware())

// Group middleware
authorized := r.Group("/admin")
authorized.Use(authMiddleware())

// Custom middleware
func authMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        token := c.GetHeader("Authorization")
        if token == "" {
            c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})
            return
        }

        user, err := validateToken(token)
        if err != nil {
            c.AbortWithStatusJSON(401, gin.H{"error": "Invalid token"})
            return
        }

        c.Set("user", user)
        c.Next()
    }
}

// Access middleware data
func handler(c *gin.Context) {
    user, _ := c.Get("user")
    // use user
}
```

## Error Handling

```go
// Centralized error handling
type AppError struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
}

func errorMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        c.Next()

        if len(c.Errors) > 0 {
            err := c.Errors.Last()
            switch e := err.Err.(type) {
            case *AppError:
                c.JSON(e.Code, e)
            default:
                c.JSON(500, gin.H{"error": "Internal server error"})
            }
        }
    }
}

// In handler
func handler(c *gin.Context) {
    if err := doSomething(); err != nil {
        c.Error(&AppError{Code: 400, Message: err.Error()})
        return
    }
}
```

## Dependency Injection

```go
type Handler struct {
    db     *sql.DB
    cache  *redis.Client
    logger *zap.Logger
}

func NewHandler(db *sql.DB, cache *redis.Client, logger *zap.Logger) *Handler {
    return &Handler{db: db, cache: cache, logger: logger}
}

func (h *Handler) GetUser(c *gin.Context) {
    user, err := h.db.FindUser(c.Param("id"))
    // ...
}

// Setup routes
func SetupRoutes(r *gin.Engine, h *Handler) {
    r.GET("/users/:id", h.GetUser)
}
```

## Best Practices

1. **Gin modes**: Use `gin.SetMode(gin.ReleaseMode)` in production
2. **Graceful shutdown**: Implement with `http.Server` and context
3. **Validation**: Use struct tags for input validation
4. **Logging**: Replace default logger with structured logging (zap/zerolog)
5. **Testing**: Use `httptest` with gin test mode

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [ngxtm](https://github.com/ngxtm)
- **Source:** [ngxtm/devkit](https://github.com/ngxtm/devkit)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-ngxtm-devkit-gin-framework
- Seller: https://agentstack.voostack.com/s/ngxtm
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
