Gin 路由

路由

核心功能

  1. 路由系统可根据请求方法、请求路径和路径参数来识别转发
  2. 可设置一个或者多个中间件用于在请求处理器前后处理特殊的事件
  3. 可以分组设置,将一个或多个中间件作用在一组多个路由上

基本语法

//构建路由对象并注册请求路径对应的处理器
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
    c.JSON(200, gin.H{
        "message": "ping",
    })
})
// 监听并在 0.0.0.0:8080 上启动服务
r.Run()

可以将路由的定义放在单独的文件中完成,如 /router/api.go :

// file: /router/api.go
func APIRouter() *gin.Engine {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "ping"
        })
    })
    // 更多的注册
    // r.POST()
    // r.DELETE()
    // r.PUT()
    return r
}

然后,在 main() 中完成调用和初始化,并启动监听:

// file /main.go
func main() {
    // 初始化路由
    r := router.APIRouter()
    // 启动服务
    r.Run()
}

请求方法

快捷方法

GET 方法外,路由系统还支持任意方式的请求:DELETEGETHEADOPTIONSPATCHPOSTPUT

通用方法

如果需要接收其他的请求方式,可以使用通用的方法 Handle 来注册:

func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers ...HandlerFunc) IRoutes

其中 httpMethod 就是请求方法字符串,例如 TRACECONNECT 等。

任意方法

若需要监听同一个请求路径的多个任意方法,可以使用 Any()

func (group *RouterGroup) Any(relativePath string, handlers ...HandlerFunc) IRoutes

处理器

handler 处理器(也被成为控制器),用来处理 HTTP 请求:

type HandlerFunc func(*Context)

handler 就是一个可以接收 *Context 类型的 (*gin.Context) 参数的函数。
处理器可以分为两类,中间件和请求处理器(也叫业务逻辑处理器)。在 router.GET() 之类的方法中,最后一个 Handler 就是请求处理器,除此之外前边的都是中间件。
处理器被调用时,会接收一个 *Context 参数,是请求上下文,用于获取请求和响应操作。

路由参数

路由参数指在请求路径中定义的参数,例如请求的 URI 是 /user/21,21 作为用户的 ID,那么 21 就是路由参数。路由参数与查询字符串有区别,例如 /user?ID=21,这个 ID=21 叫做查询字符串。
使用路由参数的好处是将动态 URL 变为静态 URL,因为请求客户端会认为路由参数不是变化的数据,因此被视为静态 URL.
如需定义带有路由参数的路径,需要使用 :param*param 的语法在路径中。

必选参数

使用 :param 的语法完成必选参数的定义,例如 /user/:ID,即可匹配 /user/21 这个 URI,但不能匹配 /user/user/。例如

router.GET("/user/:ID", func(c *gin.Context) {
    ID := c.Para("ID")
})

可选参数

使用 *param 的语法完成可选参数的定义,例如 /user/*ID 可以匹配 /user/21/user/user/ 的 URI。例如:

router.GET("/user/*ID", func(c *gin.Context) {
    ID := c.Para("ID")
})

若没有匹配到,则 ID 为空字符串。

获取参数

使用 gin.Context 对象的 c.Param("param") 来获取参数值。

路由分组

路由分组用于将多个路由进行统一的处理,例如统一的前缀,统一的中间件等。例如在需要做认证的业务逻辑时,就可以将大量的需要身份认证的路由定义在一个组中,集中设置用于认证校验的中间件。

创建分组

使用函数 router.Group() 完成分组的创建。创建时可以提供路径前缀和公用中间件:

func (group *RouterGroup) Group(relativePath string, handlers ...handlerFunc) *RouterGroup

调用该函数后,会形成一个分组路由对象,组内的路由需要使用该对象完成处理器的注册,例如:

// 简单的路由组
v1 := router.Group("/v1")
{
    v1.Post("/login", loginEndpoint)
    v1.Post("/submit", submitEndpoint)
    v1.Post("/delete", deleteEndpoint)
}

v2 := router.Group("/v2")
{
    v2.Post("/login", loginEndpoint)
    v2.Post("/submit", submitEndpoint)
    v2.Post("/delete", deleteEndpoint)
}

上面的代码创建了两个路由分组,前缀分别是 v1 和 v2。

中间件

中间件 middleware,也是一种处理器。主要用于在多个业务逻辑中间重用代码,例如认证校验、日志处理等。中间件需要附加在路由上,使用 router.User() 方法。
我们在使用 gin.Default() 初始化路由对象时,会随之附加两个中间件 LoggerRecovery,用于完成日志和恢复的相关处理:

func Default() *Engine {
    debugPrintWARNINGDefault()
    engine := New()
    // 注册中间件
    engine.Use(Logger(), Recovery())
    return engine
}

若不想使用任何中间件,可以使用函数 gin.New() 来创建空白的路由,例如:

router := gin.New()

此时的路由对象,不会自动附加任何的中间件。

启动监听

函数 router.Run() 用于启动 HTTP 监听,函数接收监听地址作为参数,默认地址为 :8080