Gin中间件

中间件介绍

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

  通俗的讲:中间件就是匹配路由前和匹配路由完成后执行的一系列操作

局部中间件

  初始中间件

  Gin 中的中间件必须是一个 gin.HandlerFunc 类型,配置路由的时候可以传递多个 func 回调函 数,最后一个 func 回调函数前面触发的方法都可以称为中间件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main
 
import (
    "fmt"
    "github.com/gin-gonic/gin"
)
 
func initMiddleware(c *gin.Context)  {
    fmt.Println("我是一个中间件")
}
func main() {
    r := gin.Default()
    // 把中间件函数加在视图函数之前
    r.GET("/index",initMiddleware, func(c *gin.Context) {
        c.String(200,"首页")
    })
    r.GET("/home",initMiddleware, func(c *gin.Context) {
        c.String(200,"home")
    })
    r.Run()
}

  c.Next()

  中间件里面加上 ctx.Next()可以让我们在路由匹配完成后执行一些操作。 比如我们统计一个请求的执行时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main
 
import (
    "fmt"
    "github.com/gin-gonic/gin"
    "time"
)
// 写一个中间件,统计视图函数运行时间
func totalTime(c *gin.Context)  {
    start:=time.Now()
 
    c.Next()//继续往后执行
 
    end:=time.Now()
    fmt.Println("视图函数运行时间为:",end.Sub(start))
}
func main() {
    r := gin.Default()
    // 把中间件函数加在视图函数之前
    r.GET("/index",totalTime, func(c *gin.Context) {
        time.Sleep(time.Second*2)
        c.String(200,"首页")
    })
 
    r.Run()
}

  多个中间件执行顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main
 
import (
    "fmt"
    "github.com/gin-gonic/gin"
    "time"
)
 
func initMiddleware(c *gin.Context) {
    fmt.Println("我是第一个中间件开始")
    c.Next() //继续往后执行
    fmt.Println("我是第一个中间件结束")
}
 
// 写一个中间件,统计视图函数运行时间
func totalTime(c *gin.Context) {
    fmt.Println("我是第二个中间件开始")
    start := time.Now()
    c.Next() //继续往后执行
    end := time.Now()
    fmt.Println("视图函数运行时间为:", end.Sub(start))
    fmt.Println("我是第二个中间件结束")
}
func main() {
    r := gin.Default()
    // 把中间件函数加在视图函数之前
    r.GET("/index", initMiddleware, totalTime, func(c *gin.Context) {
        fmt.Println("我是视图函数")
        c.String(200, "首页")
    })
 
    r.Run()
}
1
2
3
4
5
6
我是第一个中间件开始
我是第二个中间件开始
我是视图函数
视图函数运行时间为: 79.142µs
我是第二个中间件结束
我是第一个中间件结束

  c.Abort()

  Abort 是终止的意思, c.Abort() 表示终止调用该请求的剩余处理程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main
 
import (
    "fmt"
    "github.com/gin-gonic/gin"
)
 
func initMiddleware1(c *gin.Context) {
    fmt.Println("我是第一个中间件开始")
    fmt.Println("我是第一个中间件结束")
}
func initMiddleware2(c *gin.Context) {
    fmt.Println("我是第二个中间件开始")
    if c.FullPath() == "/index" {
        c.Abort() // 如果是 index请求,直接结束
    }
    fmt.Println("我是第二个中间件结束")
}
 
func main() {
    r := gin.Default()
    // 把中间件函数加在视图函数之前
    r.GET("/index", initMiddleware1, initMiddleware2, func(c *gin.Context) {
        fmt.Println("我是视图函数-index")
        c.String(200, "首页")
    })
    r.GET("/home", initMiddleware1, initMiddleware2, func(c *gin.Context) {
        fmt.Println("我是视图函数-home")
        c.String(200, "home")
    })
 
    r.Run()
} 
1
2
3
4
5
6
7
8
9
10
11
12
// 1 访问 /home
我是第一个中间件开始
我是第一个中间件结束
我是第二个中间件开始
我是第二个中间件结束
我是视图函数-home
 
// 2 访问 /index
我是第一个中间件开始
我是第一个中间件结束
我是第二个中间件开始
我是第二个中间件结束

全局中间件

  所有请求都经过此中间件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main
 
import (
    "fmt"
    "github.com/gin-gonic/gin"
)
 
func initMiddleware(ctx *gin.Context) {
    fmt.Println("全局中间件 通过 r.Use 配置") // 调用该请求的剩余处理程序
    ctx.Set("name","lqz") //设置值
    ctx.Next()
}
 
func main() {
    r := gin.Default()
    r.Use(initMiddleware)
    // 把中间件函数加在视图函数之前
    r.GET("/index",func(c *gin.Context) {
        fmt.Println("我是视图函数-index")
        fmt.Println(c.Get("name"))//取
        c.String(200, "首页")
    })
 
    r.Run()
}

在路由分组中配置中间件

  方式一:

1
2
3
4
5
6
7
shopGroup := r.Group("/shop",initMiddleware)
{
    shopGroup.GET("/index", func(c *gin.Context) {
    ...
  })
...
}

  方式二:

1
2
3
4
5
6
7
8
shopGroup := r.Group("/shop")
shopGroup.Use(initMiddleware)
{
  shopGroup.GET("/index", func(c *gin.Context) {
    ...
  })
    ...
}

中间件注意事项

  gin默认中间件

  gin.Default()默认使用了 Logger 和 Recovery 中间件,其中:

    Logger 中间件将日志写入 gin.DefaultWriter,即使配置了 GIN_MODE=release。

    Recovery 中间件会 recover 任何 panic。如果有 panic 的话,会写入 500 响应码。

    如果不想使用上面两个默认的中间件,可以使用 gin.New()新建一个没有任何默认中间件的 路由。

  gin中间件中使用 goroutine

  当在中间件或 handler 中启动新的 goroutine 时,不能使用原始的上下文(c *gin.Context), 必须使用其只读副本(c.Copy())

1
2
3
4
5
6
7
8
9
10
r.GET("/", func(c *gin.Context) {
        cCp := c.Copy()
        go func() {
            // simulate a long task with time.Sleep(). 5 seconds time.Sleep(5 * time.Second)
            // 这里使用你创建的副本
            fmt.Println("Done! in path " + cCp.Request.URL.Path)
        }()
        c.String(200, "首页")
 
    })

  

posted @   那就凑个整吧  阅读(162)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示