1.什么是路由组?

从字面意思理解,路由组指的就是一组路由。那么什么样的路由可以归类到一组呢?在实际使用中,比较常见的场景的是根据版本分组。比如下图

image-20210427215858441

2.使用语法

Gin框架中提供了一个函数Group可以将路由进行分组管理。使用语法如下:

a.不嵌套分组:

v1 := engine.Group("v1")
{
v1.GET("/path/xxx", func(context *gin.Context) {
...
})
v1.POST("/user/xxx", func(context *gin.Context) {
...
})
}

b.嵌套分组:

api := engine.Group("api")
{
user := api.Group("user")
{
user.GET("path", func(context *gin.Context) {
...
})
user.POST("path", func(context *gin.Context) {
...
})
}
}

3.多版本实战(不嵌套路由)

3.1 代码示例

//-- main.go -------
package main
import (
"github.com/gin-gonic/gin" // 引入Gin框架
"go-use/practise" // 代码示例包
)
func main() {
// 创建一个默认的路由引擎
engine := gin.Default()
// 注册路由
practise.TestRouteGroup(engine)
_ = engine.Run()
}
//--- go-use/practise/routing_use.go -------
// --- 路由组使用
func TestRouteGroup(engine *gin.Engine) {
// 路由组A(v1版本)
v1 := engine.Group("v1")
{
v1.GET("/user/login", func(context *gin.Context) {
context.JSON(200, gin.H{"msg": "v1-登录成功"})
})
v1.GET("/user/register", func(context *gin.Context) {
context.JSON(200, gin.H{"msg": "v1-注册成功"})
})
v1.GET("/user/del", func(context *gin.Context) {
context.JSON(200, gin.H{"msg": "v1-注销成功"})
})
}
// 路由组B(v2版本)
v2 := engine.Group("v2")
{
v2.GET("/user/login", func(context *gin.Context) {
context.JSON(200, gin.H{"msg": "v2-登录成功"})
})
v2.GET("/user/out", func(context *gin.Context) {
context.JSON(200, gin.H{"msg": "v2-用户退出"})
})
}
}

3.2 服务启动

[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
# 注册的路由如下
[GIN-debug] GET /v1/user/login --> go-use/practise.TestRouteGroup.func1 (3 handlers)
[GIN-debug] GET /v1/user/register --> go-use/practise.TestRouteGroup.func2 (3 handlers)
[GIN-debug] GET /v1/user/del --> go-use/practise.TestRouteGroup.func3 (3 handlers)
[GIN-debug] GET /v2/user/login --> go-use/practise.TestRouteGroup.func4 (3 handlers)
[GIN-debug] GET /v2/user/out --> go-use/practise.TestRouteGroup.func5 (3 handlers)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080

3.3 请求返回

➜ curl -X GET http://127.0.0.1:8080/v1/user/login
{"msg":"v1-登录成功"}
➜ curl -X GET http://127.0.0.1:8080/v1/user/register
{"msg":"v1-注册成功"}
➜ curl -X GET http://127.0.0.1:8080/v1/user/del
{"msg":"v1-注销成功"}
➜ curl -X GET http://127.0.0.1:8080/v2/user/login
{"msg":"v2-登录成功"}
➜ curl -X GET http://127.0.0.1:8080/v2/user/out
{"msg":"v2-用户退出"}
➜ curl -X GET http://127.0.0.1:8080/v2/user/del
404 page not found

通过上面示例发现:Gin框架虽然可以通过版本进行路由分组,但是不支持API版本继承,比如访问: http://127.0.0.1:8080/v2/user/del,期望返回{"msg":"v1-注销成功"}

4.模块分离(嵌套路由)

4.1 代码示例

//-- main.go -------
package main
import (
"github.com/gin-gonic/gin"
"go-use/practise"
)
func main() {
// 创建一个默认的路由引擎
engine := gin.Default()
// 注册路由
practise.TestRouteGroupNested(engine)
_ = engine.Run()
}
//--- go-use/practise/routing_use.go -------
// 路由嵌套分组
func TestRouteGroupNested(engine *gin.Engine) {
// 接口
api := engine.Group("api")
{
user := api.Group("user")
{
user.GET("login", func(context *gin.Context) {
context.JSON(200, gin.H{"msg": "api-登录成功"})
})
}
}
// 后台
admin := engine.Group("admin")
{
user := admin.Group("user")
{
user.GET("login", func(context *gin.Context) {
context.JSON(200, gin.H{"msg": "admin-登录成功"})
})
}
}
}

4.2 服务启动

[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
# 注册的路由如下
[GIN-debug] GET /api/user/login --> go-use/practise.TestRouteGroupNested.func1 (3 handlers)
[GIN-debug] GET /admin/user/login --> go-use/practise.TestRouteGroupNested.func2 (3 handlers)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080

4.3 请求返回

➜ curl -X GET http://127.0.0.1:8080/api/user/login
{"msg":"api-登录成功"}
➜ curl -X GET http://127.0.0.1:8080/admin/user/login
{"msg":"admin-登录成功"}