跳过正文
  1. 文章/
  2. GoLang/
  3. GoWeb/
  4. Gin/

2、路由

·1278 字·3 分钟· loading · loading · ·
GoLang GoWeb Gin
GradyYoung
作者
GradyYoung
Gin - 点击查看当前系列文章
§ 2、路由 「 当前文章 」

Gin路由系统
#

Gin的路由系统基于httprouter,经过优化后的性能是原生Go HTTP路由的40倍,是Echo等其他框架的2倍以上。Gin路由系统的主要特点包括:

  • 基于Trie树(前缀树/字典树)实现的高效路由匹配
  • 支持RESTful API设计
  • 灵活的路由分组机制
  • 支持路径参数和通配符

路由注册方式
#

Gin提供了多种路由注册方式,对应HTTP的各种方法:

// GET请求路由
router.GET("/path", HandlerFunc)

// POST请求路由
router.POST("/path", HandlerFunc)

// PUT请求路由
router.PUT("/path", HandlerFunc)

// DELETE请求路由
router.DELETE("/path", HandlerFunc)

// 任意HTTP方法
router.Any("/path", HandlerFunc)

// 自定义HTTP方法
router.Handle("OPTIONS", "/path", HandlerFunc)

路径参数
#

Gin支持在路由路径中定义参数,使用:前缀标识:

router.GET("/user/:id", func(c *gin.Context) {
    id := c.Param("id")
    c.JSON(200, gin.H{"id": id})
})

通配符路由
#

Gin支持通配符路由,使用*来匹配任意内容:

// 匹配 /user/john/send
// 匹配 /user/john/123/send
router.GET("/user/:name/*action", func(c *gin.Context) {
    name := c.Param("name")
    action := c.Param("action")
    c.String(200, "name: %s, action: %s", name, action)
})

路由分组
#

路由分组是将相关的路由按照功能、资源类型或访问权限等因素组织在一起的一种方式。Gin的路由分组功能允许开发者:

  • 为一组相关的路由定义共同的URL前缀
  • 为一组路由应用相同的中间件
  • 将路由组织成层次结构,提高代码的可读性和可维护性

路由分组在底层实现上,每个分组都是一个RouterGroup实例,它包含了前缀信息、中间件列表以及对父分组和引擎的引用,使Gin能够构建出高效的路由树。

路由分组的基本语法
#

在Gin中创建路由分组的基本语法如下:

// 创建一个路由分组
group := router.Group("/prefix")

// 在分组上定义路由
group.GET("/path", handlerFunc)
group.POST("/another", anotherHandlerFunc)

也可以使用大括号创建更清晰的分组结构:

userGroup := router.Group("/users")
{
    userGroup.GET("", getAllUsers)
    userGroup.GET("/:id", getUserByID)
    userGroup.POST("", createUser)
    userGroup.PUT("/:id", updateUser)
    userGroup.DELETE("/:id", deleteUser)
}

中间件继承
#

子分组会继承父分组的中间件,同时也可以添加自己的中间件:

// 主分组及其中间件
api := router.Group("/api")
api.Use(loggerMiddleware())

// 子分组继承父分组中间件,并添加额外中间件
authorized := api.Group("/auth")
authorized.Use(authMiddleware())

// 更深层嵌套,继承所有上层中间件,并添加自己的中间件
admin := authorized.Group("/admin")
admin.Use(adminMiddleware())

在这个例子中,对/api/auth/admin路径的访问将会依次通过loggerMiddlewareauthMiddlewareadminMiddleware

实用技巧
#

高效管理大型项目中的路由
#

路由模块化
#

在大型项目中,应该将路由定义从主文件中分离出来,实现模块化。

1、编写各模块对应的业务代码,并暴露出一个方法用来注册路由,例如 user 相关业务:

routes/user.go

package routes

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

// SetupUserRoutes 注册	user 相关路由
func SetupUserRoutes(engine *gin.Engine) {
	group := engine.Group("/user")
	group.GET("/list", func(context *gin.Context) {
		context.JSON(http.StatusOK, []gin.H{
			{"id": 1, "name": "lucy"},
			{"id": 2, "name": "tom"},
		})
	})
	group.POST("/update", func(context *gin.Context) {
		fmt.Println("TODO user/update")
		context.JSON(http.StatusOK, gin.H{
			"status": "OK",
		})
	})
}

2、编写一个统一管理路由的方法,用于统一注册路由

routes/routes.go

package routes

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

// SetupRoutes 注册路由
func SetupRoutes(engine *gin.Engine) {
	SetupUserRoutes(engine)
}

3、在主文件中注册路由

main.go

package main

import (
	"github.com/gin-gonic/gin"
	"ygang.top/gin-demo/routes"
)

func main() {
	engine := gin.Default()
	// 注册路由
	routes.SetupRoutes(engine)
	engine.Run()
}

使用结构体统一管理路由配置
#

// 路由配置结构体
type RouteInfo struct {
    Method      string
    Path        string
    Handler     gin.HandlerFunc
    Middlewares []gin.HandlerFunc
}

// 注册单个路由
func registerRoute(rg *gin.RouterGroup, route RouteInfo) {
    handlers := append(route.Middlewares, route.Handler)
    rg.Handle(route.Method, route.Path, handlers...)
}

// 注册一组路由
func registerRoutes(rg *gin.RouterGroup, routes []RouteInfo) {
    for _, route := range routes {
        registerRoute(rg, route)
    }
}

// 使用示例
func setupUserRoutes(rg *gin.RouterGroup) {
    users := rg.Group("/users")
    
    userRoutes := []RouteInfo{
        {
            Method:  "GET",
            Path:    "",
            Handler: userController.GetAllUsers,
        },
        {
            Method:  "GET",
            Path:    "/:id",
            Handler: userController.GetUser,
        },
        {
            Method:      "POST",
            Path:        "",
            Handler:     userController.CreateUser,
            Middlewares: []gin.HandlerFunc{validateUserMiddleware()},
        },
    }
    
    registerRoutes(users, userRoutes)
}

中间件作用域控制
#

中间件可能会带来性能开销,因此应该只在必要的路由上应用特定中间件。全局中间件应限制在日志、恢复等必要功能上。

中间件应该应用在尽可能小的作用域内,避免过度使用全局中间件:

// 不推荐:全局应用验证中间件
router.Use(ValidationMiddleware())

// 推荐:仅在需要的路由组上应用验证中间件
postGroup := apiGroup.Group("/posts")
postGroup.Use(ValidationMiddleware())
Gin - 点击查看当前系列文章
§ 2、路由 「 当前文章 」