添加Middleware
Gin框架的middleware 是依附 路由做的,所有 middleware 的执行都与路由有关,所以先创建一个路由:
// Creates a router without any middleware by default
r := gin.New()
然后对创建的路由每次调用 Use
方法来添加相应的 middleware,其参数为可变长参数,可以添加多个,注意:添加的Func包含业务处理Func,最多只能添加 128 个, 即: 1<<7 -1 个,如
r.Use(MyLogger(), MyError())
如果直接在注册路由的时候,添加middleware,则要注意顺序,最后的才是要执行的业务处理 Func,如
r.GET("/benchmark", MyBenchLogger(), benchEndpoint)
//MyBenchLogger()
为middleware ,// benchEndpoint
为针对这个路由需要执行的业务处理逻辑
针对路由分组的middleware添加,自行参数文档
Gin 实现Middleware的方式
在r.run()开启服务后,其在gin.go[src/github.com/gin-gonic/gin/gin.go ]文件的ServeHTTP 方法中做了封装处理,代码如下:
// ServeHTTP conforms to the http.Handler interface.
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// Context 并不是GoLang官方的库,
// 是Gin自己实现的一个库,而且是一个很重要的库
// 其middleware的实现,也是基于此库
c := engine.pool.Get().(*Context)
c.writermem.reset(w)
c.Request = req
c.reset()
// 调用处理函数,Tips:其传递了一个 Context ,这个很关键
engine.handleHTTPRequest(c)
engine.pool.Put(c)
}
请求处理函数:handleHTTPRequest,主要的代码如下
...... // 省略其它代码
// Find root of the tree for the given HTTP method
t := engine.trees
for i, tl := 0, len(t); i < tl; i++ {
if t[i].method != httpMethod {
continue
}
root := t[i].root
// Find route in tree
value := root.getValue(rPath, c.Params, unescape)
if value.handlers != nil {
c.handlers = value.handlers
c.Params = value.params
c.fullPath = value.fullPath
// 此处的调用,其实就是开始执行 Use 添加的所有Func,
// 包含业务逻辑处理的Func,注意,这是有顺序要求的【先进先出】
c.Next()
c.writermem.WriteHeaderNow()
return
}
...... // 省略其它代码
}
核心库:Context [ src/github.com/gin-gonic/gin/context.go:45 ],在这个核心库中,主要分了几类,可以多看下源码,其中关于middleware的,主要是如下函数:Next()
func (c *Context) Next() {
c.index++
// 循环-依次调用Use添加的Func
for c.index < int8(len(c.handlers)) {
c.handlers[c.index](c)
c.index++
}
}
总结:
Gin的middleware实现,就是实现了一个 Context 库,在添加路由的时候,把Func添加到一个切片中,然后循环依次执行这些Func
涉及文件:
src/github.com/gin-gonic/gin/gin.go
src/github.com/gin-gonic/gin/context.go
src/github.com/gin-gonic/gin/routergroup.go
关键Struct与Type
type Engine struct {RouterGroup,......}
type HandlerFunc func(*Context)
type HandlersChain []HandlerFunc
type Context struct {handlers,index,......}
type RouterGroup struct {Handlers, ......}