GIN中间件
2022-01-21 / 4 min read
关于中间件的使用,和原理
使用中间件
关于中间件的使用,让我想到了gin.Default()和gin.new()的区别,区别在什么呢,使用Default,默认是使用了两个全局中间件,那么我们查看default的源码,我们可以知道中间件是怎么使用的,下面我看一下default的源码:
func Default() *Engine {
debugPrintWARNINGDefault()
engine := New()
engine.Use(Logger(), Recovery())
return engine
}
这里我们直接把目光看到:engine.Use(Logger(), Recovery()),这里直接使用use就使用的中间件。所以我们知道了使用中间件使用的是,use这个方法。
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"time"
)
func main() {
//我们在前面的学习我们知道了,使用default。会默认的使用两个中间件。
//这我们为了演示使用中间件,这里我们就使用NEw创建
//r := gin.Default()
r := gin.New()
//使用logger中间件
r.Use(mylogger())
//使用recovery
r.Use(gin.Recovery())
//上面的使用方法是为全局使用的。
/**
下面这个方式,是在这个组内的路由都会使用到这个中间件。
*/
auth := r.Group("/goods", func(c *gin.Context) {
})
auth.Use(authsre)
auth.GET("/ceshi")
auth.GET("/c")
r.Run()
}
func authsre(context *gin.Context) {
fmt.Println("goods中间件")
}
func mylogger() gin.HandlerFunc{
return func(c *gin.Context) {
t := time.Now()
c.Set("example","123456")
c.Next()
end := time.Since(t)
fmt.Printf("耗时:%v \n",end)
status := c.Writer.Status()
fmt.Println("状态:",status)
}
}
func TokenReqiired()gin.HandlerFunc {
return func(c *gin.Context){
var token string
for k,v := range c.Request.Header{
if k == "x-token"{
if k == "x-token"{
token = v[0]
}
}
}
if token != "bobby"{
c.JSON(http.StatusUnauthorized,gin.H{
"msg":"未登录",
})
return
//这里只能使用c.Abort()就会阻止后面的逻辑的运行。用return 是没有用的
}
c.Next()
}
}
上面就是我们使用中间件的方式。
原理解析
这里我们发现一个问题,在中间件中,我们使用了return处理逻辑的时候,发现我们不想让后面的逻辑运行,但是使用return还是使用了,那么这是为什么呢。
这里我们需要注意的就是这中间件执行的流程
这里我们知道我们使用中间件使用的是,use去注册调用的,这个时候我们查看一个他的源码:
func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {
group.Handlers = append(group.Handlers, middleware...)
return group.returnObj()
}
点开过后,我们发现这里有一个:group.Handlers
// HandlersChain defines a HandlerFunc array.
type HandlersChain []HandlerFunc
这里发现了一个切片,然后我们再去查看运行逻辑中,我们是怎么注册路由的,然后我们点开同样发现了这个切片,然后我们对比了一下,我们发现了一个问题,也就是中间件和运行的逻辑分别是不同的handler并不是一体的,他们会按照顺序被安排到这个切片中,所以我们return是无效的,这个时候我们应该怎么办呢。
这里原理也很简单,也就是我们不想去执行这些handler的时候,我们直接把后面的删除,或者把指针移到最后面就可以了。
使用到的方法是:
c.Abort()
在上面我们书写的使用中间件源码中也有。