Gin Routing Guide
Gin framework routing patterns: groups, parameters, query strings, wildcard routes, custom validators, and handler organization.
1. Basic Routes & HTTP Methods
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default() // Logger + Recovery middleware
r.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "pong"})
})
r.POST("/articles", createArticle)
r.PUT("/articles/:id", updateArticle)
r.PATCH("/articles/:id", patchArticle)
r.DELETE("/articles/:id", deleteArticle)
r.HEAD("/articles/:id", headArticle)
r.OPTIONS("/articles", optionsArticle)
// Match any method
r.Any("/any", func(c *gin.Context) {
c.String(http.StatusOK, "method: %s", c.Request.Method)
})
r.Run(":8080")
}
2. Route Groups
func SetupRoutes(r *gin.Engine) {
// API v1 group
v1 := r.Group("/api/v1")
{
articles := v1.Group("/articles")
{
articles.GET("", ListArticles)
articles.POST("", CreateArticle)
articles.GET("/:id", GetArticle)
articles.PUT("/:id", UpdateArticle)
articles.DELETE("/:id", DeleteArticle)
}
users := v1.Group("/users")
users.Use(AuthMiddleware()) // apply middleware to group
{
users.GET("/me", GetMe)
users.PUT("/me", UpdateMe)
}
}
// Admin group with auth
admin := r.Group("/admin", AuthMiddleware(), AdminOnlyMiddleware())
{
admin.GET("/stats", GetStats)
admin.GET("/users", AdminListUsers)
}
}
3. Path Parameters & Query Strings
// Path parameters
r.GET("/articles/:id", func(c *gin.Context) {
id := c.Param("id")
c.JSON(200, gin.H{"id": id})
})
// Wildcard โ matches /files/images/logo.png
r.GET("/files/*filepath", func(c *gin.Context) {
path := c.Param("filepath") // "/images/logo.png"
c.String(200, "file: %s", path)
})
// Query parameters
// GET /search?q=golang&page=2&limit=20&sort=date
r.GET("/search", func(c *gin.Context) {
q := c.Query("q") // "" if missing
page := c.DefaultQuery("page", "1") // "1" if missing
limit := c.DefaultQuery("limit", "10")
// Bind all query params to struct
var params SearchParams
if err := c.ShouldBindQuery(¶ms); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"q": q, "page": page})
})
4. Binding & Validation
type CreateArticleRequest struct {
Title string `json:"title" binding:"required,min=5,max=300"`
Content string `json:"content" binding:"required,min=50"`
Tags []string `json:"tags" binding:"dive,min=1,max=50"`
Status string `json:"status" binding:"omitempty,oneof=draft published"`
}
func CreateArticle(c *gin.Context) {
var req CreateArticleRequest
// ShouldBindJSON โ returns error, doesn't abort
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusUnprocessableEntity, gin.H{
"error": "Validation failed",
"details": err.Error(),
})
return
}
article, err := articleService.Create(req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, article)
}
5. Custom Validators
package main
import (
"github.com/go-playground/validator/v10"
"github.com/gin-gonic/gin/binding"
)
func init() {
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
// Register custom tag
v.RegisterValidation("slug", validateSlug)
v.RegisterValidation("phone", validatePhone)
}
}
func validateSlug(fl validator.FieldLevel) bool {
import regexp
re := regexp.MustCompile(`^[a-z0-9]+(?:-[a-z0-9]+)*$`)
return re.MatchString(fl.Field().String())
}
// Usage in struct tag
type ArticleRequest struct {
Slug string `json:"slug" binding:"required,slug"`
}
// Handler groups with common logic
type ArticleHandler struct {
service ArticleService
}
func NewArticleHandler(s ArticleService) *ArticleHandler {
return &ArticleHandler{service: s}
}
func (h *ArticleHandler) Register(r *gin.RouterGroup) {
r.GET("", h.List)
r.POST("", h.Create)
r.GET("/:id", h.Get)
r.PUT("/:id", h.Update)
}
6. gin.Context Response Methods
| Method | Content-Type | Use When |
|---|---|---|
| c.JSON(code, obj) | application/json | JSON API responses |
| c.String(code, fmt, ...) | text/plain | Simple text |
| c.HTML(code, tmpl, data) | text/html | Template rendering |
| c.XML(code, obj) | application/xml | XML responses |
| c.Data(code, ct, data) | custom | Raw bytes |
| c.File(path) | โ | Serve file |
| c.Redirect(code, url) | โ | HTTP redirect |
| c.AbortWithStatus(code) | โ | Stop middleware chain |