路由分组:Group 与嵌套分组

本章解决什么问题:接口多了之后,/api/users、/api/orders 这类“同前缀 + 同中间件”的路由如果平铺注册,前缀要写很多遍,中间件也不好统一挂。路由分组把“前缀拼接”与“组级中间件”打包管理。

Group 的基本用法

r.Group(path) 返回一个 RouterGroup,组内再注册的路由自动带上组前缀:

package main

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

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

	api := r.Group("/api") // 组前缀 /api
	{
		api.GET("/users", func(c *gin.Context) {
			c.JSON(200, gin.H{"ok": true})
		})
		api.POST("/users", func(c *gin.Context) {
			c.JSON(201, gin.H{"created": true})
		})
	}

	v1 := api.Group("/v1") // 嵌套:完整前缀 /api/v1
	v1.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{"path": c.FullPath()})
	})

	r.Run(":8080")
}

代码里的大括号本身没有语法作用(Go 中就是普通块语句),只是用来缩进组内注册,让“这一块都属于 api 组”一目了然。c.FullPath() 返回命中路由的完整注册路径(含参数占位符原样),调试很有用。

组级中间件

Group 的第二大能力是“组级中间件”:注册到组里的路由执行前都会先跑组中间件,可以理解为“只对组内生效的 Use”。例如只对管理接口做鉴权:

admin := r.Group("/admin", authRequired()) // 第二参数起都是中间件
admin.GET("/stats", func(c *gin.Context) { c.JSON(200, gin.H{"ok": true}) })

其中 authRequired() 返回 gin.HandlerFunc(自定义中间件写法见第 13 章);等价写法是先 Group 再调用 group.Use(authRequired())。

嵌套分组的典型场景

版本化 API 常用嵌套分组:v1/v2 各自成树,方便灰度与新老版本并存。分组可以任意嵌套,内层前缀叠加在外层之上,中间件也按“外层先、内层后”的顺序叠加执行。

关键点

  • Group 只做两件事:拼前缀、挂中间件,不引入新的请求语义。
  • 组级中间件按“引擎级 → 外层组 → 内层组 → 路由级”的顺序叠加执行(下一章讲执行机制)。
  • 分组不影响 NoRoute、NoMethod 等全局行为,它们仍挂在引擎上。

小结

分组把前缀管理与局部中间件合二为一,版本化 API 与管理后台这类布局基本都靠它。下一章深入中间件的执行顺序与 c.Next/c.Abort。

笔记加载中…