GoLang-Gin框架-中间件的实现

添加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, ......}

官方文档

https://gin-gonic.com/docs/examples/using-middleware/