Gin框架入门(四)—中间件 - Go语言中文社区

Gin框架入门(四)—中间件


官方文档:https://godoc.org/github.com/gin-gonic/gin
官方地址:https://github.com/gin-gonic/gin

无中间件

func main() {
//创建一个无中间件路由
router := gin.New()
router.Run()
}

默认中间件

func main() {
// 默认启动方式,包含 Logger、Recovery 中间件
router:=gin.Default()
router.GET("/", func(context *gin.Context) {
	context.JSON(200,gin.H{
		"goods_name":"牛奶",
	})
})
router.Run()
}

在这里插入图片描述
结论: 上图控制台输出便是gin.Logger中间件输出访问记录到控制台

中间件的2种定义方式

//自定义中间件第1种定义方式
func CustomRouterMiddle1(c *gin.Context)  {
	t := time.Now()
	fmt.Println("我是自定义中间件第1种定义方式---请求之前")
	//在gin上下文中定义一个变量
	c.Set("example", "CustomRouterMiddle1")
	//请求之前
	c.Next()
	fmt.Println("我是自定义中间件第1种定义方式---请求之后")
	//请求之后
	//计算整个请求过程耗时
	t2 := time.Since(t)
	log.Println(t2)

}

//自定义中间件第2种定义方式
func CustomRouterMiddle2() gin.HandlerFunc{
	return func(c *gin.Context) {
		t := time.Now()
		fmt.Println("我是自定义中间件第2种定义方式---请求之前")
		//在gin上下文中定义一个变量
		c.Set("example", "CustomRouterMiddle2")
		//请求之前
		c.Next()
		fmt.Println("我是自定义中间件第2种定义方式---请求之后")
		//请求之后
		//计算整个请求过程耗时
		t2 := time.Since(t)
		log.Println(t2)
	}
}



func main() {
	
	r := gin.New()
	
	//测试时下面两个中间件选择一个,注释一个
	r.Use(CustomRouterMiddle1)
	r.Use(CustomRouterMiddle2())

	r.GET("/test", func(c *gin.Context) {
		example := c.MustGet("example").(string)

		//
		log.Println(example)
	})

	// 监听本地8080端口
	r.Run(":8080")
}

访问 http://localhost:8080/test 效果图1:
在这里插入图片描述
访问 http://localhost:8080/test 效果图2:
在这里插入图片描述
结论: 第1种和第2种定义方式实质上都是一样的,都是定义一个参数类型为*gin.Context的函数。相对而言第1种不需要加(),更加简洁,个人推荐第1种。
还有一个就是大家可以看到效果图1和效果图2的打印顺序不一样,按照代码的语句顺序效果图1才是正确的,但是效果图2也没错。原因是这段代码的执行时间很短,4个输出语句都处于竞争状态,谁先抢到就运行一个时间片,然后才能轮到其他输出语句到达下一个时间片再抢,所以,结果不会唯一。这是本人对于这个的理解,等以后深入了解源码再和大家分享,如果有错,欢迎指出。

路由中间件使用

func RouterMiddle1(c *gin.Context)  {
	fmt.Println("我是路由中间件1")
}

func RouterMiddle2(c *gin.Context)  {
	fmt.Println("我是路由中间件2")
}

func oneRouterMiddleHandle() gin.HandlerFunc{
	return func(c *gin.Context) {
		fmt.Println("我是业务处理函数")
	}
}

func main() {
	//创建一个无中间件路由
	router := gin.New()
	// 对于每个路由中间件,您可以添加任意数量的路由中间件
	router.GET("/oneRouterMiddle", RouterMiddle1,RouterMiddle2,oneRouterMiddleHandle())
	// 默认监听本地 0.0.0.0:8080 即localhost:8080 或 127.0.0.1:8080
	router.Run()
}

在这里插入图片描述
结论: 从上图可以看出单个路由的中间件是可以添加多个的,并按照添加的函数顺序执行的,所以我们把业务函数放在最后一个

路由组中间件使用

func GroupRouterGoodsMiddle1(c *gin.Context)  {
	fmt.Println("我是goods路由组中间件1")
}

func GroupRouterGoodsMiddle2(c *gin.Context) {
	fmt.Println("我是goods路由组中间件2")
}

func GroupRouterOrderMiddle1(c *gin.Context) {
	fmt.Println("我是order路由组中间件1")
}

func GroupRouterOrderMiddle2(c *gin.Context) {
	fmt.Println("我是order路由组中间件2")
}

func main() {
	//创建一个无中间件路由
	router := gin.New()
	router.Use(gin.Logger())

	//第1种路由组使用方式 可以添加多个处理函数 但是不知道为什么 官方举例的这第一种方式用不了
	router.Group("/goods", GroupRouterGoodsMiddle1, GroupRouterGoodsMiddle2)
	router.GET("/goods/add", func(context *gin.Context) {
		fmt.Println("/goods/add")
	})


	//第2种路由组使用方式
	orderGroup := router.Group("/order")
	orderGroup.Use(GroupRouterOrderMiddle1, GroupRouterOrderMiddle2)
	{
		orderGroup.GET("/add", func(context *gin.Context) {
			fmt.Println("/order/add")

		})

		orderGroup.GET("/del", func(context *gin.Context) {
			fmt.Println("/order/del")

		})

		//orderGroup下再嵌套一个testGroup
		testGroup:=orderGroup.Group("/test", func(context *gin.Context) {
			fmt.Println("order/test下的中间件")
		})

		testGroup.GET("/test1", func(context *gin.Context) {
			fmt.Println("order/test/test1的函数")
		})
	}

	router.Run()
}

访问 http://localhost:8080/order/add
在这里插入图片描述
访问 http://localhost:8080/order/del
在这里插入图片描述
访问order下不存在的路由,显示404, 并且中间件不执行
在这里插入图片描述
访问 http://localhost:8080/order/test/test1
在这里插入图片描述
结论1: 填写正确的路由组和路由,中间件先执行,并按照传入函数的顺序执行。
结论2: 填写正确的路由组,错误的路由,中间件不执行,并返回404错误。
结论3: 路由组中还可以嵌套路由组

全局中间件使用

func GlobalMiddle(c *gin.Context){
	fmt.Println("我是全局中间件")
}

func main() {
//创建一个无中间件路由
router := gin.New()

//使用自定义的全局中间件
router.Use(GlobalMiddle)

router.GET("/", func(context *gin.Context) {
	fmt.Println("我是/")
})

router.Run()
}

在这里插入图片描述

自定义中间件的执行顺序

这里我就不用代码展示了。大家在前面代码上测试下就行了,这里直接告诉大家结果。
结论: 全局中间件 > 路由组中间件 > 路由中间件
全局中间件最先执行

疑似官方Bug

在这里插入图片描述
上图是官方示例,在第1种路由组使用方式,实际测试用不了。不知道是我太菜还是真是官方的bug,如果有小伙伴发现什么可以和我评论交流。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_36162966/article/details/91383006
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢