Gin.RouterGroup:分组、中间件与路径组合

在 Gin 框架中,真正支撑路由能力的不是 gin.Engine,而是 gin.RouterGroup

gin.Engine 本质上是嵌入了 RouterGroup 的增强结构(type Engine struct { *RouterGroup ... }),因此你调用 r.GET()r.Group() 时,实际上是在操作一个 RouterGroup 实例。

RouterGroup 是 Gin 的核心抽象,它提供了:

  • 路径前缀管理(自动拼接)
  • 中间件作用域隔离
  • 嵌套分组能力
  • 统一的方法注册接口(GET/POST/Use/Static 等)

理解 RouterGroup 的工作方式,是掌握 Gin 架构设计的关键

HTTP 方法路由

go 复制代码
// 所有 HTTP 方法

GET(path string, handlers ...HandlerFunc) IRoutes

POST(path string, handlers ...HandlerFunc) IRoutes

PUT(path string, handlers ...HandlerFunc) IRoutes

DELETE(path string, handlers ...HandlerFunc) IRoutes

PATCH(path string, handlers ...HandlerFunc) IRoutes

HEAD(path string, handlers ...HandlerFunc) IRoutes

OPTIONS(path string, handlers ...HandlerFunc) IRoutes

ANY(path string, handlers ...HandlerFunc) IRoutes

  

// 自定义方法

Handle(httpMethod, relativePath string, handlers ...HandlerFunc) IRoutes

中间件管理

go 复制代码
// 添加中间件
Use(middleware ...HandlerFunc) IRoutes

分组创建

go 复制代码
// 创建子分组
Group(component string, handlers ...HandlerFunc) *RouterGroup

静态文件服务

go 复制代码
// 静态文件
StaticFile(relativePath, filepath string) IRoutes
Static(relativePath, root string) IRoutes
StaticFS(relativePath string, fs http.FileSystem) IRoutes

路径组合规则

go 复制代码
// 基础路径组合规则
r := gin.Default()
api := r.Group("/api")           // basePath: "/api"
v1 := api.Group("/v1")           // basePath: "/api/v1"  
users := v1.Group("/users")      // basePath: "/api/v1/users"

// 最终路由:
// users.GET("/profile") → 实际路径: /api/v1/users/profile
// users.POST("/create") → 实际路径: /api/v1/users/create

基础用法

go 复制代码
func main() {
    r := gin.Default()
    
    // Engine 本身就是一个 RouterGroup
    r.GET("/", handler)  // r 是 *RouterGroup
    
    // 创建分组
    api := r.Group("/api")  // 返回 *RouterGroup
    api.GET("/users", handler)
    api.POST("/users", handler)
}

分组嵌套

go 复制代码
func main() {
    r := gin.Default()
    
    // 一级分组
    api := r.Group("/api")
    {
        api.GET("/users", handler1)
        api.POST("/users", handler2)
        
        // 二级分组
        v1 := api.Group("/v1")
        {
            v1.GET("/users", handler3)
            v1.POST("/users", handler4)
        }
        
        v2 := api.Group("/v2")
        {
            v2.GET("/users", handler5)
        }
    }
}

中间件分组

go 复制代码
func main() {
    r := gin.Default()
    
    // 公共路由组(无中间件)
    public := r.Group("/public")
    {
        public.GET("/info", handler1)
    }
    
    // 受保护路由组(带认证中间件)
    protected := r.Group("/api")
    protected.Use(AuthMiddleware())  // 该组所有路由都使用认证中间件
    {
        protected.GET("/profile", handler2)
        protected.POST("/posts", handler3)
        
        // 在分组内再创建子分组
        admin := protected.Group("/admin")
        admin.Use(AdminMiddleware())  // 管理员中间件
        {
            admin.GET("/dashboard", handler4)
            admin.DELETE("/users/:id", handler5)
        }
    }
}

完整示例

go 复制代码
package main

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

func AuthMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 简单认证逻辑
        token := c.GetHeader("Authorization")
        if token == "" {
            c.JSON(401, gin.H{"error": "Unauthorized"})
            c.Abort()
            return
        }
        c.Next()
    }
}

func AdminMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 简单管理员验证
        role := c.GetHeader("Role")
        if role != "admin" {
            c.JSON(403, gin.H{"error": "Forbidden"})
            c.Abort()
            return
        }
        c.Next()
    }
}

func main() {
    r := gin.Default()
    
    // 根分组(Engine 本身)
    r.GET("/", func(c *gin.Context) {
        c.JSON(200, gin.H{"message": "Root path"})
    })
    
    // API 分组
    api := r.Group("/api")
    {
        api.GET("/health", func(c *gin.Context) {
            c.JSON(200, gin.H{"status": "ok"})
        })
        
        // 用户相关接口
        users := api.Group("/users")
        users.Use(AuthMiddleware())  // 用户接口需要认证
        {
            users.GET("/", func(c *gin.Context) {
                c.JSON(200, gin.H{"users": []string{"user1", "user2"}})
            })
            users.GET("/:id", func(c *gin.Context) {
                id := c.Param("id")
                c.JSON(200, gin.H{"id": id, "name": "John"})
            })
            users.POST("/", func(c *gin.Context) {
                c.JSON(201, gin.H{"message": "User created"})
            })
        }
        
        // 管理员接口
        admin := api.Group("/admin")
        admin.Use(AuthMiddleware(), AdminMiddleware())  // 需要认证+管理员权限
        {
            admin.GET("/dashboard", func(c *gin.Context) {
                c.JSON(200, gin.H{"message": "Admin dashboard"})
            })
            admin.GET("/users", func(c *gin.Context) {
                c.JSON(200, gin.H{"message": "Admin users list"})
            })
        }
    }
    
    // 静态文件
    static := r.Group("/static")
    static.Static("/files", "./files")  // 静态文件服务
    
    r.Run()
}
相关推荐
索西引擎1 天前
【React】Redux 中间件机制:副作用处理与数据流增强的形式化分析
前端·react.js·中间件
糖果店的幽灵1 天前
【DeepAgents 从入门到精通】Context Management 上下文管理
java·人工智能·后端·spring·中间件·langgraph·deepagents
熊文豪2 天前
【金仓数据库征文】不装中间件的 MySQL→金仓在线迁移,mysql_fdw 全流程,和一个差点漏掉的 emoji
数据库·mysql·中间件·电科金仓
拆房老料4 天前
ONLYOFFICE AI Agent 深度解析:在线 Office 正从编辑器走向智能工作平台
人工智能·中间件·编辑器·word·开源软件
知行合一。。。4 天前
LangChain--08--中间件(Middleware)
中间件·langchain
●VON4 天前
鸿蒙 PC Markdown 编辑器可靠性设计:未保存内容的崩溃恢复闭环
华为·中间件·编辑器·harmonyos·鸿蒙
fuquxiaoguang5 天前
中间件的“价值重估”:传统同质化竞争终结,AI智能编排时代开启
人工智能·中间件
小邓的技术笔记6 天前
解析 gin 接收到 http 请求是怎么处理的
网络协议·http·gin
fuquxiaoguang6 天前
中间件的“结构性升级”:当智能编排成为政企采购的“硬指标”
中间件·ai智能体·ai原生
C137的本贾尼7 天前
第七篇:消息队列(MQ)——就是个带存储的异步通信管道
java·开发语言·中间件