gin 框架(四) | 青训营笔记

100 阅读2分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 16 天

定义中间件

Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等。

Gin中的中间件必须是一个 gin.HandlerFunc 类型。

下面是一个简单的中间件,用来计算耗时

func middle(c *gin.Context) {
    start := time.Now()
    c.Next() // 调用后续的处理函数
    cost := time.Since(start)
    fmt.Println("time: ", cost)
}

Next 继续后面的处理函数

Abort 阻止后续的处理函数

可以看出,go的中间件就是一个钩子函数。仔细观察可以发现,中间件和处理请求时的处理函数相似。

查看 get 源码

image.png

可以很清晰的看出,使用的处理函数本质就是中间件。这里又不得不感慨 go 的简洁。

注册中间件

路由注册

由源码可以看出,中间件参数是一个不定参数,所以直接填入即可。

r.GET("/", middle, func(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{"message": "Hello World"})
})

路由组注册

image.png

查看 gin 路由组的源码,可以看出和 GET 的是一样的。故注册方式一样

userGroup := r.Group("/user", middle)

全局注册

全局注册要使用 Use 函数

r.Use(middle)

查看 use 的源码

image.png

同样的不定参数,同样的味道。

中间件原理

学会了定义和注册就可以完成基本的使用了,有的小伙伴可能就会有疑问,中间件的执行顺序是什么样子,下面我们就来看看。

中间件会按照添加顺序执行。流程入下图

image.png

gin 的中间件维护了一个 HandlerChain 函数数组和一个索引 index。每增加一个中间件就 index++。

用户验证登录案例

func AuthMiddleWare() gin.HandlerFunc {
    return func(c *gin.Context) {
        cookie, err := c.Cookie("session_id") // 获取cookie
        if err != nil || cookie == "" {
            c.JSON(401, gin.H{"error": "未登录"})
            c.Abort() // 中断请求
            return
        }
        c.Next() // 继续请求
    }
}

参考

  1. 特性 | Gin Web Framework (gin-gonic.com)
  2. 快速入门 | 正文 |《Gin 框架中文文档 1.7》| Go 技术论坛 (learnku.com)
  3. Restful风格的API · Go语言中文文档 (topgoer.com)
  4. Gin 中间件的实现原理 - 掘金 (juejin.cn)
  5. Gin框架介绍及使用 | 李文周的博客 (liwenzhou.com)