Go语言学习路

Gin框架理论知识

2021-08-17  本文已影响0人  TZX_0710

1.数据如何在gin中流转

func main(){
  r:=gin.Default()//1.初始化相关参数
    //2.ping将路由及处理handler注册到路由树种
    r.GET("/ping",func(c *gin.Context){
        c.JSON(200,gin.H{"message":"pong"})
    })
    //3.启动服务 r.Run()其实调用的是err=http.ListenAndServe(address,engine)gin其实利用了net/http的处理过程
    r.Run()
}

2.Engine

在整个gin框架最重要的一个struct就是engine,它包含路由,中间件,相关配置信息等,Engine代码主要就在gin.go中。Engine中比较重要的几个属性, 其他的属性暂时全部省略掉

type Engine struct {
    RouterGroup // 路由
    pool             sync.Pool  // context pool
    trees            methodTrees // 路由树
    // html template及其他相关属性先暂时忽略
}

3.New(), Default()

New()主要干的事情:

  1. 初始化了Engine
  2. 将RouterGroup的Handlers(数组)设置成nil, basePath设置成/
  3. 为了使用方便, RouteGroup里面也有一个Engine指针, 这里将刚刚初始化的engine赋值给了RouterGroup的engine指针
  4. 为了防止频繁的context GC造成效率的降低, 在Engine里使用了sync.Pool, 专门存储gin的Context

Default:

  Default()跟New()几乎一模一样, 就是调用了gin内置的Logger(), Recovery()中间件.

4. Use()

func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes {
   engine.RouterGroup.Use(middleware...)
   engine.rebuild404Handlers()
   engine.rebuild405Handlers()
   return engine
}

Use()就是gin的引入中间件的入口了. 仔细分析这个函数, 不难发现Use()其实是在给RouteGroup引入中间件的.

5.addRoute()

这段代码就是利用method, path, 将handlers注册到engine的trees中. 注意这里为什么是HandlersChain呢, 可以简单说一下, 就是将中间件和处理函数都注册到method, path的tree中了.

func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {
    ...
    root := engine.trees.get(method)
    if root == nil {
        root = new(node)
        engine.trees = append(engine.trees, methodTree{method: method, root: root})
    }
    root.addRoute(path, handlers)
}

6. Run系列函数

Run, RunTLS, RunUnix, RunFd 这些函数其实都是最终在调用net/http的http服务.

7.

ServeHTTP

这个函数相当重要了, 主要有这个函数的存在, 才能将请求转到gin中, 使用gin的相关函数处理request请求.

t := engine.trees

for i, tl := 0, len(t); i < tl; i++ {
    if t[i].method != httpMethod {
        continue
    }
    root := t[i].root

    handlers, params, tsr := root.getValue(path, c.Params, unescape)
    if handlers != nil {
        c.handlers = handlers
        c.Params = params
        c.Next()
        c.writermem.WriteHeaderNow()
        return
    }
    ...
}
//利用request中的path, 从Engine的trees中获取已经注册的handler
func (c *Context) Next() {
    c.index++
    for c.index < int8(len(c.handlers)) {
        c.handlers[c.index](c)
        c.index++
    }
}
在Next()执行handler
func(c *gin.Context) {
    c.JSON(200, gin.H{
        "message": "pong",
    })
}
上一篇下一篇

猜你喜欢

热点阅读