Gin HandlersChain 调用解析


前言

  Gin 可以说是Golang WEB应用比较广泛框架,在博主使用时一直对其内部中间件和Group handle的调用比较好奇,这次仅从FuncHandle的调用做一次解析。


一、HandlersChain 是什么?

在gin的context.go文件中存在下述定义

type Context struct {
	// ... 忽略上面 
	handlers HandlersChain
	index    int8
	// ... 忽略下面
}

// HandlersChain defines a HandlerFunc array.
type HandlersChain []HandlerFunc

// HandlerFunc defines the handler used by gin middleware as return value.
type HandlerFunc func(*Context)

通过代码可以,HandlersChain 实质就是一个方法数组,每个方法的方法签名为 func(*Context)。
这个方法数组记录了形如:gin.Use(func..), gin.Get("", func), gin.Group("", func)中出现的func,并在gin初始化的时候按顺序,将这些func放到同一个数组,等待被依次调用。

二、调用方式

func (c *Context) Next() {
	c.index++
	for c.index < int8(len(c.handlers)) {
		c.handlers[c.index](c)
		c.index++
	}
}

可以看出来Next内部维护了一个for循环来依次调用方法链中的方法。并用一个全局的index来维护context方法调用指针,防止出现每调用一次Next就全部调用一次所有方法。

context的Next就是方法链的调用入口。源码的调用如下

// gin.go
func (engine *Engine) handleHTTPRequest(c *Context) {
	// ... 忽略上列代码
	if value.handlers != nil {
		c.handlers = value.handlers
		c.fullPath = value.fullPath
		c.Next()
		c.writermem.WriteHeaderNow()
		return
	}
	// ... 忽略下列代码
}

三、源码模拟

package main

func main() {
	// 初始化
	context := NewContext()
	for i := 0; i < 5; i++ {
		temp := i
		context.add(func(ctx *Context) {
			// 注释next后  4 3 2 1 0
			// 不注释为    0 1 2 3 4
			//ctx.Next()
			print(temp)
		})
	}
	// 入口
	context.Next()
}

func NewContext() *Context {
	return &Context{
		funcIndex:   -1,
		FuncHandles: make([]FuncHandle, 0),
	}
}

type Context struct {
	funcIndex   int
	FuncHandles []FuncHandle
}

type FuncHandle func(ctx *Context)

// 调用
func (this *Context) Next() {
	this.funcIndex++
	for ; this.funcIndex < len(this.FuncHandles); this.funcIndex++ {
		this.FuncHandles[this.funcIndex](this)
	}
}

// 添加Handle
func (this *Context) add(handle FuncHandle) {
	this.FuncHandles = append(this.FuncHandles, handle)
}

四、总结

通过上述代码我们可以总结出,Next只是一个方法的调用入口。
如果func中不写c.Next(),会由顶层调用(最开始调用Next()的方法)进行for循环遍历;如果func写了c.Next()就想到与是一个链式的调用。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值