gin series-middleware

The Gin framework allows developers to add their own hook functions during the processing of requests. This hook function is called middleware. Middleware is suitable for processing some common business logic, such as login authentication, permission verification, data paging, logging, time-consuming statistics

Define middleware

The middleware in Gin must be a gin.HandlerFunc type

Entry case

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
)

func indexHandler(c *gin.Context) {
	fmt.Println("index in ...")
	c.JSON(http.StatusOK, gin.H{
		"msg": "indx",
	})
}

//定义一个中间件
func m1(c *gin.Context)  {
	fmt.Println("m1 in ....")
}

func main() {
	r := gin.Default()
	//GET(relativePath string, handlers ...HandlerFunc) IRoutes
	r.GET("/index",m1,indexHandler)
	//r.GET("/index", func(c *gin.Context) {
	//	c.JSON(http.StatusOK, gin.H{
	//		"msg": "indx",
	//	})
	//})
	r.Run(":9090")
}

[GIN-debug] Listening and serving HTTP on :9090
m1 in ....
index in ...
[GIN] 2020/04/21 - 15:21:31 |?[97;42m 200 ?[0m|       998.3µs |       127.0.0.1 |?[97;44m GET     ?[0m "/index"
package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

func indexHandler(c *gin.Context) {
	fmt.Println("index in ...")
	c.JSON(http.StatusOK, gin.H{
		"msg": "indx",
	})
}

//定义一个中间件:统计耗时
func m1(c *gin.Context)  {
	fmt.Println("m1 in ....")
	//计时
	start := time.Now()
	c.Next() //调用后续的处理函数 执行indexHandler函数
	//c.Abort() //阻止调用后续的处理函数
	cost := time.Since(start)
	fmt.Println("cost:%v\n", cost)
	//输出
	// m1 in ....
	//index in ...
	//cost:%v
	// 996.8µs
}

func main() {
	r := gin.Default()
	//GET(relativePath string, handlers ...HandlerFunc) IRoutes
	r.GET("/index",m1,indexHandler)  //先执行m1函数再执行indexHandler函数
	//r.GET("/index", func(c *gin.Context) {
	//	c.JSON(http.StatusOK, gin.H{
	//		"msg": "indx",
	//	})
	//})
	r.Run(":9090")
}

Register middleware

In the gin framework, you can add any number of middleware for each route.

Register for global routing

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

func indexHandler(c *gin.Context) {
	fmt.Println("index in ...")
	c.JSON(http.StatusOK, gin.H{
		"msg": "indx",
	})
}

//定义一个中间件:统计耗时
func m1(c *gin.Context)  {
	fmt.Println("m1 in ....")
	//计时
	start := time.Now()
	c.Next() //调用后续的处理函数 执行indexHandler函数
	//c.Abort() //阻止调用后续的处理函数
	cost := time.Since(start)
	fmt.Println("cost:%v\n", cost)
	fmt.Println("m1 out")
	//输出
	// [GIN-debug] Listening and serving HTTP on :9090
	//m1 in ....
	//m2 in ....
	//index in ...
	//m2 out
	//cost:%v
	// 997.3µs
	//m1 out
}


func m2(c *gin.Context)  {
	fmt.Println("m2 in ....")
	c.Next() //调用后续的处理函数
	fmt.Println("m2 out")
}

func main() {
	r := gin.Default()
	r.Use(m1,m2) //全局注册中间件函数m1,m2    洋葱模型   类似递归调用
	//GET(relativePath string, handlers ...HandlerFunc) IRoutes
	//r.GET("/index",m1,indexHandler)  //先执行m1函数再执行indexHandler函数
	r.GET("/index",indexHandler)
	r.GET("/shop", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"msg": "index",
		})
	})
	r.GET("/user", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"msg": "index",
		})
	})
	r.Run(":9090")
}
package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

func indexHandler(c *gin.Context) {
	fmt.Println("index in ...")
	c.JSON(http.StatusOK, gin.H{
		"msg": "indx",
	})
}

//定义一个中间件:统计耗时
func m1(c *gin.Context)  {
	fmt.Println("m1 in ....")
	//计时
	start := time.Now()
	c.Next() //调用后续的处理函数 执行indexHandler函数
	//c.Abort() //阻止调用后续的处理函数
	cost := time.Since(start)
	fmt.Println("cost:%v\n", cost)
	fmt.Println("m1 out")
	//输出
	// [GIN-debug] Listening and serving HTTP on :9090
	//m1 in ....
	//m2 in ....
	//m2 out
	//cost:%v
	// 997.8µs
	//m1 out
}


func m2(c *gin.Context)  {
	fmt.Println("m2 in ....")
	//c.Next() //调用后续的处理函数
	c.Abort() //阻止后续调用
	//return   //return 立即结束m2函数 
	//m1 in ....
	//m2 in ....
	//cost:%v
	// 0s
	//m1 out

	fmt.Println("m2 out")
}

//func authMiddleware(c *gin.Context)  {   //通常写成闭包
//	//是否登陆的判断
//	//if 是登陆用户
//	//c.Next()
//	//else
//	//c.Abort()
//}

func authMiddleware(doCheck bool)gin.HandlerFunc {   //开关注册
	//连接数据库
	//或着其他准备工作
	return func(c *gin.Context) {
		if doCheck {
			//是否登陆的判断
			//if 是登陆用户
			//c.Next()
			//else
			//c.Abort()
		} else {
			c.Next()
		}
	}
	
}

func main() {
	r := gin.Default()
	r.Use(m1,m2,authMiddleware(true)) //全局注册中间件函数m1,m2    洋葱模型   类似递归调用
	//GET(relativePath string, handlers ...HandlerFunc) IRoutes
	//r.GET("/index",m1,indexHandler)  //先执行m1函数再执行indexHandler函数
	r.GET("/index",indexHandler)
	r.GET("/shop", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"msg": "index",
		})
	})
	r.GET("/user", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"msg": "index",
		})
	})
	r.Run(":9090")
}

Register separately for a route

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

//定义一个中间件:统计耗时
func m1(c *gin.Context)  {
	fmt.Println("m1 in ....")
	//计时
	start := time.Now()
	c.Next() //调用后续的处理函数 执行indexHandler函数
	//c.Abort() //阻止调用后续的处理函数
	cost := time.Since(start)
	fmt.Println("cost:%v\n", cost)
	fmt.Println("m1 out")
}

func main() {
	r := gin.Default()
	r.GET("/user", m1, func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"msg": "index",
		})
	})
	//m1 in ....
	//cost:%v
	// 0s
	//m1 out
	r.Run(":9090")
}
import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

func indexHandler(c *gin.Context) {
	fmt.Println("index in ...")
	c.JSON(http.StatusOK, gin.H{
		"msg": "indx",
	})
}

//定义一个中间件:统计耗时
func m1(c *gin.Context)  {
	fmt.Println("m1 in ....")
	//计时
	start := time.Now()
	c.Next() //调用后续的处理函数 执行indexHandler函数
	//c.Abort() //阻止调用后续的处理函数
	cost := time.Since(start)
	fmt.Println("cost:%v\n", cost)
	fmt.Println("m1 out")
}


func m2(c *gin.Context)  {
	fmt.Println("m2 in ....")
	//c.Next() //调用后续的处理函数
	c.Abort() //阻止后续调用
	//return   //return 立即结束m2函数
	//m1 in ....
	//m2 in ....
	//cost:%v
	// 0s
	//m1 out

	fmt.Println("m2 out")
}

func main() {
	r := gin.Default()
	r.GET("/user", m1,m2, func(c *gin.Context) {  //可以单独多个路由
		c.JSON(http.StatusOK, gin.H{
			"msg": "index",
		})
	})
	//[GIN-debug] Listening and serving HTTP on :9090
	//m1 in ....
	//m2 in ....
	//m2 out
	//cost:%v
	// 0s
	//m1 out
	r.Run(":9090")
}

Register middleware for routing groups

func main() {
	//路由组注册中间件方法1:
	xxGroup := r.Group("/xx", authMiddleware(true))
	{
		xxGroup.GET("/index", func(c *gin.Context) {
			c.JSON(http.StatusOK, gin.H{"msg":"xxGroup"})
		})
	}
	//路由组注册中间件方法2:
	xx2Group := r.Group("/xx")
	xx2Group.Use(authMiddleware(true))
	{
		xxGroup.GET("/index", func(c *gin.Context) {
			c.JSON(http.StatusOK, gin.H{"msg":"xxGroup"})
		})
	}
	r.Run(":9090")
}

Access values ​​across middleware

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

func indexHandler(c *gin.Context) {
	fmt.Println("index in ...")
	name, ok := c.Get("name")   //从上下文中取值,跨中间件存取值
	if !ok {
		name = "匿名用户"
	}
	c.JSON(http.StatusOK, gin.H{
		"msg": name,
	})
}

//定义一个中间件:统计耗时
func m1(c *gin.Context)  {
	fmt.Println("m1 in ....")
	//计时
	start := time.Now()
	c.Next() //调用后续的处理函数 执行indexHandler函数
	//c.Abort() //阻止调用后续的处理函数
	cost := time.Since(start)
	fmt.Println("cost:%v\n", cost)
	fmt.Println("m1 out")
}


func m2(c *gin.Context)  {
	fmt.Println("m2 in ....")
	c.Set("name","zisefeizhu")  //在上下文中设置c的值
	fmt.Println("m2 out")
}

func authMiddleware(doCheck bool)gin.HandlerFunc {   //开关注册
	//连接数据库
	//或着其他准备工作
	return func(c *gin.Context) {
		if doCheck {
			//是否登陆的判断
			//if 是登陆用户
			c.Next()
			//else
			//c.Abort()
		} else {
			c.Next()
		}
	}

}

func main() {
	r := gin.Default()
	r.Use(m1,m2,authMiddleware(true)) //全局注册中间件函数m1,m2    洋葱模型   类似递归调用
	//GET(relativePath string, handlers ...HandlerFunc) IRoutes
	//r.GET("/index",m1,indexHandler)  //先执行m1函数再执行indexHandler函数
	r.GET("/index",indexHandler)
	r.Run(":9090")
}

Middleware considerations

gin.Default()

gin.Default () uses Logger and Recovery middleware by default, where Logger middleware writes logs to gin.DefaultWriter, even if GIN_MODE = release is configured. Recovery middleware will recover any panic. If there is panic, a 500 response code will be written. If you don't want to use the two default middleware above, you can use gin.New () to create a new route without any default middleware.

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

func indexHandler(c *gin.Context) {
	fmt.Println("index in ...")
	name, ok := c.Get("name")   //从上下文中取值,跨中间件存取值
	if !ok {
		name = "匿名用户"
	}
	c.JSON(http.StatusOK, gin.H{
		"msg": name,
	})
}

//定义一个中间件:统计耗时
func m1(c *gin.Context)  {
	fmt.Println("m1 in ....")
	//计时
	start := time.Now()
	c.Next() //调用后续的处理函数 执行indexHandler函数
	//c.Abort() //阻止调用后续的处理函数
	cost := time.Since(start)
	fmt.Println("cost:%v\n", cost)
	fmt.Println("m1 out")
}


func m2(c *gin.Context)  {
	fmt.Println("m2 in ....")
	c.Set("name","zisefeizhu")  //在上下文中设置c的值
	fmt.Println("m2 out")
}

func authMiddleware(doCheck bool)gin.HandlerFunc {   //开关注册
	//连接数据库
	//或着其他准备工作
	return func(c *gin.Context) {
		if doCheck {
			//是否登陆的判断
			//if 是登陆用户
			c.Next()
			//else
			//c.Abort()
		} else {
			c.Next()
		}
	}

}

func main() {
	//r := gin.Default()  //默认使用Logger()和Recovery()中间件
	r := gin.New()
	r.Use(m1,m2,authMiddleware(true)) //全局注册中间件函数m1,m2    洋葱模型   类似递归调用
	r.GET("/index",indexHandler)
	r.GET("/shop", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"msg": "index",
		})
	})
	r.GET("/user", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"msg": "index",
		})
	})
	r.Run(":9090")
}

[GIN-debug] Listening and serving HTTP on :9090
m1 in ....
m2 in ....
m2 out
index in ...
cost:%v
 1.0137ms
m1 out

Use goroutine in gin middleware

When starting a new goroutine in middleware or handler, the original context (c * gin.Context) cannot be used, and its read-only copy (c.Copy ()) must be used.

//定义一个中间件:统计耗时
func m1(c *gin.Context)  {
	fmt.Println("m1 in ....")
	//计时
	start := time.Now()
	go funcXX(c.Copy()) //在funcXX中只能使用c的拷贝
	c.Next() //调用后续的处理函数 执行indexHandler函数
	//c.Abort() //阻止调用后续的处理函数
	cost := time.Since(start)
	fmt.Println("cost:%v\n", cost)
	fmt.Println("m1 out")
}

Guess you like

Origin www.cnblogs.com/zisefeizhu/p/12747417.html