gin框架分析二:gin初始化,默认配置实例构建过程
gin的函数调用流程
gin的函数调用过程大概如下图:
GIN函数调用过程第一步构建GIN实例,第二步构建GIN路由,第三步则是启动http.server包,坚挺HTTP请求,并将请求处理交给gin框架,gin又通过路由匹配寻找到对应的handler去具体处理每一个请求。
GIN的初始化过程
我们会从上面函数调用图的方法顺序开始过源码,并尝试弄清楚gin在各个阶段都干了些什么内容。
得到默认配置的gin实例
main函数代码中通过 gin.Default() 函数可以获取到一个默认配置的engine实例,Default()函数如下:
func Default() *Engine { debugPrintWARNINGDefault() engine := New() engine.Use(Logger(), Recovery()) return engine }
debugPrintWARNINGDefault()函数首先被调用,其检测go版本是否在1.14+,如果不满足条件则给出一个警告,仅仅是一个警告而不做其他操作。
func debugPrintWARNINGDefault() { if v, e := getMinVer(runtime.Version()); e == nil && v <= ginSupportMinGoVer { debugPrint(`[WARNING] Now Gin requires Go 1.14+. `) } debugPrint(`[WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached. `) }
通过调用New()函数,构造出一个默认配置项的engin实例。
func New() *Engine { debugPrintWARNINGNew() engine := &Engine{ RouterGroup: RouterGroup{ Handlers: nil, basePath: "/", root: true, }, FuncMap: template.FuncMap{}, RedirectTrailingSlash: true, RedirectFixedPath: false, HandleMethodNotAllowed: false, ForwardedByClientIP: true, RemoteIPHeaders: []string{"X-Forwarded-For", "X-Real-IP"}, TrustedPlatform: defaultPlatform, UseRawPath: false, RemoveExtraSlash: false, UnescapePathValues: true, MaxMultipartMemory: defaultMultipartMemory, trees: make(methodTrees, 0, 9), delims: render.Delims{Left: "{{", Right: "}}"}, secureJSONPrefix: "while(1);", trustedProxies: []string{"0.0.0.0/0", "::/0"}, trustedCIDRs: defaultTrustedCIDRs, } engine.RouterGroup.engine = engine engine.pool.New = func() any { return engine.allocateContext() } return engine }
其中gin对于Context的处理使用了一个sync.Pool来处理,这样可以在每次对于Context的实例都不用重复生成,可以尽可能重复利用已经存在的实例。
engine.Use(Logger(), Recovery())方法默认为engine添加Logger和Recovery两个中间件,并保存于RouterGroup.Handlers中,然后在路由添加处理器是合并进各个路由处理中调用,这就是为什么通过gin.Default()生成实例后对于添加的路由处理方法会有3个handler的原因。
例如:
router.GET("/ping", func(c *gin.Context) { c.String(200, "pong %d", counter) counter = counter + 1 })
如上路由处理对应的路由信息为:
进入engine.Use(Logger(), Recovery())方法:
func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes { engine.RouterGroup.Use(middleware...) engine.rebuild404Handlers() engine.rebuild405Handlers() return engine }
其调用父类的Use方法把默认中间件添加到RouterGroup.Handlers,同时构建了404和405的异常处理钩子函数。
至此,gin.Defaults()创建了一个包含两个默认中间件、一个可重复利用Context并在Context实例不足时生成实例的gin engin,在获得默认配置的的gin实例后接下来的任务就是构建路由树和对应的处理方法。
本文来自博客园,作者:一朵野生菌,转载请注明原文链接:https://www.cnblogs.com/xmy20051643/p/17064132.html