Gin中间件执行顺序

初始化demo项目

1
2
3
mkdir -p gin-middleware-demo
cd gin-middleware-demo
go mod init github.com/kbsonlong/gin-middleware-demo

middleware/middle.go

 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
34
35
package middleware

import (
	"fmt"
	"time"

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

func MdOne() gin.HandlerFunc {
	return func(c *gin.Context) {
		fmt.Println("开始执行第一个 gin 中间件:" + time.Now().String())
		c.Next()

		fmt.Println("第一个 gin 中间件返回内容:" + time.Now().String())
	}
}

func MdTwo() gin.HandlerFunc {
	return func(c *gin.Context) {
		fmt.Println("开始执行第二个 gin 中间件:" + time.Now().String())
		c.Next()

		fmt.Println("第二个 gin 中间件返回内容:" + time.Now().String())
	}
}

func MdThree() gin.HandlerFunc {
	return func(c *gin.Context) {
		fmt.Println("开始执行第三个 gin 中间件:" + time.Now().String())
		c.Next()

		fmt.Println("第三个 gin 中间件返回内容:" + time.Now().String())
	}
}

routers/router.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package routers

import (
	"github.com/gin-gonic/gin"
	"github.com/kbsonlong/gin-middleware-demo/middleware"
)

func InitRouter() *gin.Engine {
	r := gin.New()
	r.Use(middleware.MdOne())
	r.Use(middleware.MdTwo())
	r.Use(middleware.MdThree())
	gin.SetMode("debug")

	r.GET("/", func(ctx *gin.Context) {
		ctx.JSON(200, gin.H{
			"message": "test",
		})
	})
	return r
}

main.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package main

import (
	"github.com/kbsonlong/gin-middleware-demo/routers"
)

func main() {

	router := routers.InitRouter()

	router.Run()
}

运行测试

1
2
go mod tidy
go run main.go
1
2
3
4
5
6
7
8
9
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /                         --> github.com/kbsonlong/gin-middleware-demo/routers.InitRouter.func1 (4 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080

另一终端执行

1
2
curl 127.0.0.1:8080
{"message":"test"}

可以看到控制台输出内容

1
2
3
4
5
6
开始执行第一个 gin 中间件:2022-07-08 17:18:57.499033 +0800 CST m=+3.029327751
开始执行第二个 gin 中间件:2022-07-08 17:18:57.499215 +0800 CST m=+3.029509918
开始执行第三个 gin 中间件:2022-07-08 17:18:57.499218 +0800 CST m=+3.029513043
第三个 gin 中间件返回内容:2022-07-08 17:18:57.499295 +0800 CST m=+3.029589876
第二个 gin 中间件返回内容:2022-07-08 17:18:57.499298 +0800 CST m=+3.029593335
第一个 gin 中间件返回内容:2022-07-08 17:18:57.4993 +0800 CST m=+3.029594876

调整中间件Use顺序

1
2
3
4
5
6
7
......
	r.Use(middleware.MdOne())

	r.Use(middleware.MdThree())
	r.Use(middleware.MdTwo())
	gin.SetMode("debug")
......

第二个中间件和第三个中间件顺序对调

1
2
3
4
5
6
开始执行第一个 gin 中间件:2022-07-08 17:20:57.702026 +0800 CST m=+2.567931210
开始执行第三个 gin 中间件:2022-07-08 17:20:57.702215 +0800 CST m=+2.568120210
开始执行第二个 gin 中间件:2022-07-08 17:20:57.702218 +0800 CST m=+2.568123543
第二个 gin 中间件返回内容:2022-07-08 17:20:57.702305 +0800 CST m=+2.568210460
第三个 gin 中间件返回内容:2022-07-08 17:20:57.702308 +0800 CST m=+2.568214043
第一个 gin 中间件返回内容:2022-07-08 17:20:57.702311 +0800 CST m=+2.568216293

可以看到第三个中间件在第二个中间件之前执行

注释第三个中间件Next

1
2
3
4
5
6
7
8
func MdThree() gin.HandlerFunc {
	return func(c *gin.Context) {
		fmt.Println("开始执行第三个 gin 中间件:" + time.Now().String())

		// c.Next()
		fmt.Println("第三个 gin 中间件返回内容:" + time.Now().String())
	}
}
1
2
3
4
5
6
开始执行第一个 gin 中间件:2022-07-08 17:22:43.132983 +0800 CST m=+4.061931376
开始执行第三个 gin 中间件:2022-07-08 17:22:43.133126 +0800 CST m=+4.062074668
第三个 gin 中间件返回内容:2022-07-08 17:22:43.133128 +0800 CST m=+4.062076751
开始执行第二个 gin 中间件:2022-07-08 17:22:43.13313 +0800 CST m=+4.062078210
第二个 gin 中间件返回内容:2022-07-08 17:22:43.133203 +0800 CST m=+4.062151335
第一个 gin 中间件返回内容:2022-07-08 17:22:43.133205 +0800 CST m=+4.062153460

总结

Gin中间件的调用顺序与Use顺序有关,代码运行顺序和Next前后顺序有关。

  • Next之前代码先进先出
  • Next之后代码后进先出
  • 没有引用Next代码直接运行
0%