中间件
参考:https://learnku.com/articles/66234
- 结构
- 中间件是函数
- 中间件函数被放在调用链上
- 调用链的末尾是路由path对应的函数
- 执行过程
- net/http包调用到gin的serverHTTP
- 参考:go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/gin.go:506
- 通过path找到路由对应的处理链,赋值给context
- 参考:go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/gin.go:553
- 执行c.next()启动链条
- net/http包调用到gin的serverHTTP
问题:中间件函数中为啥要调用next,不调用,能继续执行完后面的中间件吗
参考:https://blog.dianduidian.com/post/gin-%E4%B8%AD%E9%97%B4%E4%BB%B6next%E6%96%B9%E6%B3%95%E5%8E%9F%E7%90%86%E8%A7%A3%E6%9E%90/
- 可以
- 即使中间件没有调用next函数,那么后续中间件和handles也会执行
- 中间件中调用next函数,会先执行后续中间件,然后回到这个中间件,继续执行next函数之后的代码
- 参考:/Users/didi/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:165
- 这里的c.index是一个共用的值
- 在
c.handlers[c.index](c)
执行的时候可能会变,所以虽然在中间件中有调用next函数,但是中间价并不会重复执行
- 参考:/Users/didi/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:165
- 提前结束,不能使用return,要使用abort
- abort:
c.index = abortIndex
- abort:
代码参考
package mainimport ("encoding/json""fmt")/****上下文 */// Context 上下文type Context struct {Keysmap[string]interface{}handles HandleChainindex int}type HandleChain []func(ctx *Context)func (c *Context) Render(resultCode int, data interface{}) {d, _ := json.Marshal(data)fmt.Println("resultCode:", resultCode, " , data:", string(d))}func (c *Context) Next() {c.index++for c.index < len(c.handles) {c.handles[c.index](c)c.index++}}func (c *Context) reset() {c.index = -1}/** 路由 */// router 路由type router struct {Handlers map[string]HandleChain}type Group struct {Handles HandleChain}func (r *router) RegisterRoute(url string, f func(*Context), group Group) () {if r.Handlers == nil {r.Handlers = make(map[string]HandleChain)}r.Handlers[url] = append(r.Handlers[url], group.Handles...)r.Handlers[url] = append(r.Handlers[url], f)}func (g *Group) Use(f func(*Context)) {g.Handles = append(g.Handles, f)}func (r *router) Run(url string, c *Context) () {c.handles = r.Handlers[url]c.reset()c.Next()}/** 业务代码 */// PlusController 加法func PlusController(c *Context) {a := c.Keys["a"].(int)b := c.Keys["b"].(int)c.Render(200, plus(a, b))}// plus 加法函数func plus(a, b int) int {return a + b}// MultiController 乘法func MultiController(c *Context) {a := c.Keys["a"].(int)b := c.Keys["b"].(int)c.Render(200, multi(a, b))}// multi 加法函数func multi(a, b int) int {return a * b}/** 主函数 */func main() {r := router{}group1 := Group{Handles: HandleChain{func(ctx *Context) {fmt.Println("testMiddle1")},func(ctx *Context) {ctx.Next()fmt.Println("testMiddle2")},}}group2 := Group{Handles: HandleChain{func(ctx *Context) {fmt.Println("testMiddle3")ctx.Next()fmt.Println("testMiddle4")},}}r.RegisterRoute("*", MultiController,group1)r.RegisterRoute("+", PlusController,group2)fmt.Println("----------")r.Run("*", &Context{Keys: map[string]interface{}{"a": 34, "b": 245}})fmt.Println("----------")r.Run("+", &Context{Keys: map[string]interface{}{"a": 34, "b": 245}})}