gin series-middleware

El marco Gin permite a los desarrolladores agregar sus propias funciones de enlace durante el procesamiento de solicitudes. Esta función de enlace se llama middleware. El middleware es adecuado para procesar alguna lógica comercial común, como autenticación de inicio de sesión, verificación de permisos, paginación de datos, registro, estadísticas que consumen mucho tiempo, etc.

Definir middleware

El middleware en Gin debe ser un tipo gin.HandlerFunc

Caso de entrada

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")
}

Registrar middleware

En el marco de gin, puede agregar cualquier cantidad de middleware para cada ruta.

Registrarse para el enrutamiento global

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")
}

Registrarse por separado para una ruta

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")
}

Registrar middleware para grupos de enrutamiento

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")
}

Acceda a valores en el 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")
}

Consideraciones de middleware

gin.Default ()

gin.Default () usa el middleware Logger and Recovery de forma predeterminada, donde: El middleware Logger escribe registros en gin.DefaultWriter, incluso si GIN_MODE = release está configurado. El middleware de recuperación recuperará cualquier pánico. Si hay pánico, se escribirá un código de respuesta 500. Si no desea usar los dos middleware predeterminados anteriores, puede usar gin.New () para crear una nueva ruta sin ningún middleware predeterminado.

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 en gin middleware

Al iniciar una nueva rutina en un middleware o controlador, el contexto original (c * gin.Context) no se puede usar, y su copia de solo lectura (c.Copy ()) se debe usar.

//定义一个中间件:统计耗时
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")
}

Supongo que te gusta

Origin www.cnblogs.com/zisefeizhu/p/12747417.html
Recomendado
Clasificación