Gin 是一个轻量级 web 框架,具有简洁、易用、高效等特性,是目前 Go 开源社区最火热的项目之一。
ps: 默认读者有一定的 Go 基础,本文将只对 Gin 核心数据结构、处理流程进行介绍。
Engine
func main() { |
一切都将开始于一个最简单的 demo 程序。其中我们通过 gin.Default()获取了一个*gin.Engine对象,我们通过追踪这个函数取查看下这个对象的结构。排除掉一些功能配置参数后,谨慎下如下三个核心结构。
type Engine struct { |
RouterGroup
type RouterGroup struct { |
RouterGroup 是我们使用路由组时直接相关的一个数据结构。
func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) *RouterGroup { |
Handlers 是我们通过
Group方法注册的全量公共中间件,使用 copy 的方式进行装载(早期使用 append),数量最多 63 个,由const abortIndex int8 = math.MaxInt8 >> 1决定。func (group *RouterGroup) combineHandlers(handlers HandlersChain) HandlersChain {
finalSize := len(group.Handlers) + len(handlers)
assert1(finalSize < int(abortIndex), "too many handlers")
mergedHandlers := make(HandlersChain, finalSize)
copy(mergedHandlers, group.Handlers)
copy(mergedHandlers[len(group.Handlers):], handlers)
return mergedHandlers
}basePath 是路由访问的全量路径。
engine 为指向我们创建的 Engine 实例的指针。在
New函数中指定。
sync.Pool
go 提供的是一个临时对象存储池,这里暂时不做详细介绍,可以大致看看其结构。
相关解析文档已经更新至于此处。
type Pool struct { |
methodTrees
type methodTrees []methodTree |
type methodTree struct { |
type node struct { |
每一个 http 方法都会创建一个对应的路由树(压缩前缀树,基数树)。基数树结构大致如下:
压缩前缀树的每一个节点都会保存其所有子节点的公共最长前缀。如图左侧分支存储app、apple、application三个单词。
- path 保存最长公共前缀
- indices 为子树的索引
- wildChild 子节点包含通配符标记
- nType 节点类型
- priority 优先级额,配合 indeces 构建索引使用, 每多一个子节点增加一
children []*node子节点,:param节点排在最后,根据 prority 进行排序- handlers 同 Group 中类似,保存全量中间件和处理函数
- fullPath 全量路径
执行流程
Default
func Default(opts ...OptionFunc) *Engine { |
debugPrintWARNINGDefault()如果使用 Debug 模式则会答应警告信息,包括 go 版本是否适配,加载 recover 和 logger 中间件提示。
New
func New(opts ...OptionFunc) *Engine { |
Group
介绍路由组结构时已经介绍过了,比较简单的一个过程。
Get
创建 Get 方法路由,其他方法于此类似这里就至追踪 Get 这一个方法。
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes { |
func (group *RouterGroup) handle(httpMethod, relativePath string, handlers HandlersChain) IRoutes { |
func (engine *Engine) addRoute(method, path string, handlers HandlersChain) { |
添加路由的过程有点点复杂,就可以结合流程图查看。分支结构比较多。。。
func (n *node) addRoute(path string, handlers HandlersChain) { |
- 本文作者: Tiny Beer
- 本文链接: https://tinybeer.github.io/2024/05/28/Gin核心源码解析/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!
