Gin框架学习笔记 | 青训营

47 阅读4分钟

简介

  • Gin是一个golang的微框架,封装比较优雅,API友好,源码注释比较明确,具有快速灵活,容错方便等特点
  • 对于golang而言,web框架的依赖要远比Python,Java之类的要小。自身的net/http足够简单,性能也非常不错
  • 借助框架开发,不仅可以省去很多常用的封装带来的时间,也有助于团队的编码风格和形成规范

特性

  • 快速

    • 基于Radix 树的路由,小内存占用。没有反射。可预测的 API 性能。
  • 支持中间件

    • 传入的 HTTP 请求可以由一系列中间件和最终操作来处理。 例如:Logger,Authorization,GZIP,最终操作 DB。
  • Crash处理

    • Gin 可以 catch 一个发生在 HTTP 请求中的 panic 并 recover 它。这样,你的服务器将始终可用。
  • JSON验证

    • Gin 可以解析并验证请求的 JSON,例如检查所需值的存在。
  • 路由组

    • 更好地组织路由。是否需要授权,不同的 API 版本…… 此外,这些组可以无限制地嵌套而不会降低性能。
  • 错误管理

    • Gin 提供了一种方便的方法来收集 HTTP 请求期间发生的所有错误。最终,中间件可以将它们写入日志文件,数据库并通过网络发送。
  • 内置渲染

    • Gin 为 JSON,XML 和 HTML 渲染提供了易于使用的 API。
  • 可扩展性

    • 新建一个中间件非常简单

路由注册流程

核心数据结构

gin.Engine

该结构中包含三个核心对象:

  • RouterGroup: 路由组,和路由管理相关
  • 路由树数组trees: 标准库本身的路由是不区分请求方法的,也就是说注册一个路由后,GET、POST都能匹配到该路由。这显然不是我们想要的,我们希望的是同一个路由在不同的请求方法下,由不同的逻辑进行处理。其实就是通过路由树实现的,gin的针对每个请求方法都有一棵路由树
  • context对象池: gin.Context是gin框架暴露给开发的另一个核心对象,可以通过该对象获取请求信息,业务处理的结果也是通过该对象写回客户端的。为了实现context对象的复用,gin基于sync.Pool实现了对象池

RouterGroup

路由组的目的是为了实现配置的复用。

比如有一组对food的请求: /food/add、/food/query、/food/update等,我们希望在注册路由时尽量简单(不要每次都写/food),并且与food相关的请求使用一组单独的middleware(与其他对象的请求隔离开),这时候就可以使用路由组。

type RouterGroup struct {
    // 路由组处理函数链,其下路由的函数链将结合路由组和自身的函数组成最终的函数链
    Handlers HandlersChain
    // 路由组的基地址,一般是其下路由的公共地址
    basePath string
    // 路由组所属的Engine,这里构成了双向引用
    engine *Engine
    // 该路由组是否位于根节点,基于RouterGroup.Group创建路由组时此属性为false
    root bool
}

HandlersChain处理器链

用于收集该路由组下注册的middleware函数,在运行时,会按顺序执行HandlersChain中的注册的函数。

type HandlerFunc func(*Context)

// HandlersChain defines a HandlerFunc slice.
// NOTE: 路由处理函数链,运行时会根据索引先后顺序依次调用
type HandlersChain []HandlerFunc

执行流程

一般情况下使用gin框架开发时使用默认的engine即可,因为相对于直接使用gin.New()创建Engine对象,它只是多注册了两个中间件。 一般流程如下:

  1. 创建并初始化Engine对象
  2. 注册middleware
  3. 注册路由及处理函数
  4. 服务端口监听

请求处理

对请求处理入口就是Engine.ServerHTTP方法 其核心处理逻辑如下:

  1. 从context对象池取一个可用的context对象,后续交互就是靠这个对象完成的
  2. http.ResponseWriterhttp.Request对象保存到context中。我们通过context获取请求参数、写入响应,其实是因为其底层封装了这两个对象的方法
  3. 调用Engine的handleHTTPRequest方法,对请求进行处理。注意到其参数已经变成了gin.Context了。
  4. 请求处理完毕,回收context,以便下次复用。

请求绑定和响应渲染

  • 请求绑定

    • gin提供了一系列的方式,用于从请求中获取参数和数据等信息
  • 响应渲染

    • 就是将响应结构体序列化为字节数据,再写入http.ResponseWriter