Gin框架源码学习
2023-06-17 14:59:28 0 举报
AI智能生成
Gin框架源码知识地图
作者其他创作
大纲/内容
Engine
Engine是Gin框架的核心,所有代码都集成在这个结构体里
将Engine结构,会得到以下几个模块
Router 路由
Middleware 中间件
Context 上下文
输入输出
其他
Engine的启动和优雅关闭
启动
New()
Default()
关闭
普通关闭
优雅关闭
关键字段详解
Router
数据结构:数组+前缀树
数组用来存储请求类型:GET,POST,DELETE等
前缀树用来存储具体的路径
前缀树的叶子节点上存的有函数链
前缀树的特点
可以存储较多类型的路由
静态路由
/book/info
动态路由
/book/:id
/book/:id/info
可以配置特殊作用的路由
节省空间,本质相当提取公共项
查询效率上比MAP低一些
数据结构上不如MAP轻巧,简单
前缀树的其他使用场景
敏感词检索
省市地区的检索
搜索框推荐信息
核心方法
核心结构
RouterGroup
Handlers 一个函数链,底层是一个数组,装的是中间件的方法,子Group会继承父的中间件
basePath 定义的Group的主路径
engine 核心引擎的指针。需要注意,基于主Group创造出来的子Group们不仅会使用主中间件还会共用一个主引擎
root 是否为根Group,只有我们New出来的主引擎自带的Group这里才会是true
注意,整个RouterGroup只负责绑定路由树,不负责匹配
methodTree
method 方法类型:GET,POST等
root 方法类型对应的具体路由树
这个结构就是主引擎中用来存储路由树的结构
node
路由树的节点信息
path 节点路径,比如上面的blog,a,bout等等
fullPath 完整路径
wildChild 通配符标识,比如带有:id的节点,这个值就是true
indices 字母索引,对应的就是上边的a,下面的about和article的b和r 也就意味着,这个分支下面还有至少两个分支
priority 优先级,当前节点的子节点越多,这个值会越大
children 当前节点的所有子节点
nType 节点类型
static: 静态节点(默认)
root: 根节点
catchAll: 带有通配符的节点,也就是*
param: 参数节点
handlers 函数链
核心方法
addRoute() 添加一个路径
addRoute 这个无法并发安全。言外之意就是,这个前缀树结构不是并发安全的。
getValue() 匹配一个路径
其他方法
Map(go 自带的HTTP)
正则匹配(gorilla/mux)
Middleware
核心思路:AOP
通过将横切关注点从主要业务逻辑中分离出来,然后以模块化的方式进行管理和重用
也是编程范式的一种
绝大多数的现代框架的中间件模块都是基于AOP的思想来设计的
实现思路:通过函数链的方式实现洋葱模型
函数链
也叫链式函数,将多个Func按照一定的顺序组合起来
函数链实现洋葱模型有两个思路
索引
函数注入
洋葱模型
一种软件架构模式,旨在实现松耦合、可维护和可测试的应用程序
核心思想是将应用程序分为多个层次,每个层次具有不同的职责和依赖关系。这些层次按照一定的规则进行组织,以便实现解耦和可测试性。
层级
外部层(Outermost Layer)
应用服务层(Application Services Layer)
领域层(Domain Layer)
基础设施层(Infrastructure Layer)
特点
解耦性
可测试性
可维护性
其他
他也是领域驱动模型(DDD)的一种实践
核心方法
函数链
type HandlersChain []HandlerFunc
type HandlerFunc func(*Context)
RouterGroup
参考路由器
Func
Use()
Group()
combineHandlers()
流程
Next()
Next 函数链操作的核心,也是洋葱模式的一种实现方式
Abort()
Abort 用来将函数链的索引设置为最大值,会终止函数链的执行
自带的中间件
Log
用来打印请求日志,包括起始时间,耗时,URL,参数,CODE 码等等
Recover
大多数的框架都会有一个最外层的recover中间件,以确保出现panic时,服务还能正常使用。
Context
官方Context的原理
空的Context
context.Background()
获取一个根节点。相当于拿到了Context的Root节点。注意在代码中不要随便使用。
context.TODO()
获取一个空节点。理论上可以把他当做根节点,请不要这样搞。这个方法只会用在需要传一个CTX,但实际不产生任何用处时,充当占位符。
其他Context
context.WithCancel()
常用的一种方法,返回一个可以取消的上下文。当父辈执行取消操作时,会将信号同步给他的子孙们,他们同时也会响应取消当前的操作。
context.WithTimeout()
最常使用的一个方法。带有一个超时机制的上下文。可以手动触发取消也可以在超时之后自动触发取消。
context.WithDeadline()
不常用的一个方法。 带有一个时间点的上下文。可以手动触发取消也可以在到了时间点之后自动触发取消。
context.WithValue()
最不常用的方法,通常情况下,我们是不会在上下文里穿一些数据的。最常见的只有传Trace和Token
Gin Context
CONTEXT CREATION
用来重置或者复制一个Context
reset()
将现有Context的绝大多数字段全部重置为初始值
Copy()
拷贝一个当前的Context,提供给其他协程使用
handlers,skippedNodes,errors等不会被复制,在使用时需要注意
Index会被直接设置为abort的值,也就意味着,这个Context实际上是没有办法向下继续执行的。
FLOW CONTROL
控制流,我们常用的Next和Abort就在这一模块
Next()
通过Index来确定当前需要执行的handler,这里会和中间件联动
Abort()
直接将Index设置到abort的状态,后续方法也不会再执行了
ERROR MANAGEMENT
错误管理
Error()
该方法会把err信息装到Context的Errors切片中,非常适合中间件使用
使用方最终可以将Errors的错误信息全部写进日志中
注意他返回的Error是gin框架中自定义的错误
METADATA MANAGEMENT
元数据管理,就是Key中存储的数据,gin帮我做了一套数据转化的方法,直接获取我们需要的字段类型
Set() 向一个带锁的MAP中写入一个值的经典写法 ,值得学习
该方法被用在两个地方
从Pool中获取一个新的Context时
需要重置当前Context时
Get()
MustGet() 唯一特殊的方法。查找的键值不存在,直接Panic。
其他 一套获取指定类型的方法,核心就是反射,没啥技巧
注意,我们仍然可以调用delete()方法删掉一个元数据,因为他的底层是个MAP
INPUT DATA
获取用户输入的数据,看着一大堆实际上关键函数就几个我们后续会展开
Param() 获取动态参数的方法。
GetQueryArray() 获取URL参数的核心方法,其他方法都是基于此方法。
GetPostFormArray() 获取Form表单的核心方法,其他方法都是基于此方法。
get() 获取MAP类型返回值的核心方法,不常用。
ShouldBindWith() 绝大多数bind方法的核心。后续我们专门展开讲一讲。
RESPONSE RENDERING
返回内容,主要是设置response的header和body
Header() 用来设置一些头部信息。
SetCookie() 底层是http.SetCookie的封装。
Render() 其他返回方法的底层方法。我们常用的json,jsonp,html都是基于这个方法实现的。
File() 返回一个文件,实现下载功能时会用到。
Stream() gin 理论上确实可以返回一个数据流,只是用的很少。
CONTENT NEGOTIATION
用来和客户端协商请求的响应格式的。有些时候客户端会带上需要的返回内容,XML或者Json。
Negotiate() 根据客户端的需求,返回恰当的类型。非常智能,但用的很少。
GOLANG.ORG/X/NET/CONTEXT
对官方Context接口的具体实现,我们可以细细品一品。
Bind&Render
Bind
Render
Other
参数校验
Request
0 条评论
下一页