Gin框架学习记录 - 中间件的使用
hanpy

Gin 框架中间件的使用方式

官方文档中有关中间件的内容(这个文档写的真的是看的费劲啊…..)
不使用默认的中间件 | Gin Web Framework (gin-gonic.com)
使用 BasicAuth 中间件 | Gin Web Framework (gin-gonic.com)
使用中间件 | Gin Web Framework (gin-gonic.com)
在中间件中使用 Goroutine | Gin Web Framework (gin-gonic.com)

默认的中间件

gin.Default() 会使用 Logger(), Recovery() 两个中间件
Logger 中间件将日志写入 gin.DefaultWriter,即使你将 GIN_MODE 设置为 release
Recovery 中间件会 recover 任何 panic。如果有 panic 的话,会写入500。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Default 使用 Logger 和 Recovery 中间件
engine := gin.Default()

// github.com/gin-gonic/gin@v1.7.2/gin.go
func Default() *Engine {
debugPrintWARNINGDefault()
engine := New()
engine.Use(Logger(), Recovery())
return engine
}

// github.com/gin-gonic/gin@v1.7.2/logger.go
func Logger() HandlerFunc {
return LoggerWithConfig(LoggerConfig{})
}

// github.com/gin-gonic/gin@v1.7.2/recovery.go
func Recovery() HandlerFunc {
return RecoveryWithWriter(DefaultErrorWriter)
}

全局中间件

全局中间件顾名思义就是所有的请求都会使用到的。
上面的Logger(), Recovery()两个中间件就是全局中间件。

单个路由使用

1
2
3
4
5
6
7
8
9
10
r := gin.New()
// 路由使用单个中间件
r.GET("/m1", gin.Logger(), func(ctx *gin.Context) {
// ...
})
// 单个路由使用多个中间件
r.GET("/m2", gin.Logger(), gin.Recovery(), func(ctx *gin.Context) {
// ...
})
r.Run(":9090")

路由组中使用

1
2
3
4
5
6
7
8
r := gin.New()
uGroup := r.Group("/user").Use(gin.Logger())
{
uGroup.GET("/get", func(ctx *gin.Context) {
// ...
})
}
r.Run(":9090")

自定义中间件的使用

gin.Logger()gin.Recovery() 的源码中可以看到,定义中间件,只需要返回类型是gin.HandlerFunc 即可
c.Next() : 而要终止执行时则需调用
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
// 自定义中间件
func MyMiddleware() gin.HandlerFunc {
return func(ctx *gin.Context) {
fmt.Println("MyMiddleware--请求前")
token := ctx.DefaultQuery("token", "")
if token != "hanpy" {
// 终止执行调用这个函数
ctx.JSON(400, gin.H{"errorMsg": "token验证失败"})
ctx.Abort()
}
// 继续执行调用这个函数
ctx.Next()
fmt.Println("MyMiddleware--请求后")
}
}

r := gin.New()
r.Use(gin.Logger())
r.GET("/check", MyMiddleware(), func(ctx *gin.Context) {
fmt.Println("输出之前...")
ctx.JSON(200, gin.H{"status": "OK!"})
})
r.Run(":9090")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#1
$ curl --url "http://127.0.0.1:9090/check"
{"errorMsg":"token验证失败"}

#1 控制台输出
MyMiddleware--请求前
MyMiddleware--请求后
[GIN] 2023/03/27 - 22:09:02 | 400 | 147.361µs | 127.0.0.1 | GET "/check"

#2
$ curl --url "http://127.0.0.1:9090/check?token=hanpy"
{"status":"OK!"}

#2 控制台输出
MyMiddleware--请求前
输出之前...
MyMiddleware--请求后
[GIN] 2023/03/27 - 22:09:41 | 200 | 187.88µs | 127.0.0.1 | GET "/check?token=hanpy"

多个中间件的执行

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
// 自定义中间件1
func OneMiddleware() gin.HandlerFunc {
return func(ctx *gin.Context) {
fmt.Println("One中间件-请求前")
ctx.Next()
fmt.Println("One中间件-请求后")
}
}

// 自定义中间件2
func TwoMiddleware() gin.HandlerFunc {
return func(ctx *gin.Context) {
fmt.Println("Two中间件-请求前")
ctx.Next()
fmt.Println("Two中间件-请求后")
}
}

func main() {
r := gin.Default()
r.GET("/multipleMiddleware", OneMiddleware(), TwoMiddleware(), func(ctx *gin.Context) {
fmt.Println("multipleMiddleware方法输出")
})
_ = r.Run(":9090")
}
1
2
3
4
5
6
7
8
9
10
#1 
$ curl --url "http://127.0.0.1:9090/multipleMiddleware"

#1 控制台输出
One中间件-请求前
Two中间件-请求前
multipleMiddleware方法输出
Two中间件-请求后
One中间件-请求后
[GIN] 2023/03/27 - 22:22:59 | 200 | 18.089µs | 127.0.0.1 | GET "/multipleMiddleware"