【Gin】深度解析:在Gin框架中优化应用程序流程的责任链设计模式(下)
前言
本次文章分为上下两部分,上部分为对理论的介绍,下部分为具体的底层代码深度剖析和编程实践,感兴趣的伙伴不要错过哦~
关键的类图和时序图
(1)类图
责任链模式包含以下几个主要角色:
Handler
(抽象处理者):
声明一个处理请求的接口,通常包含一个指向下一个处理者的引用。
MiddlerWare
(具体处理者):
Gin的中间件实现抽象处理者的处理方法,并根据自身的处理能力决定是否处理请求,如果不能处理则将请求传递给下一个处理者。
Client
(客户端):
创建一个具体处理者对象的链,并向链上的第一个处理者对象发送请求。
图 28 责任链模式类图
(2)时序图
图 29 责任链模式时序图
主程序的流程
图 30 责任链模式主程序流程图
程序模块之间的调用关系
下图为程序各模块之间的调用关系:
图 31 责任链模式程序模块调用图
由上图31可知,责任链模式主要有如下3个角色:
(1) IRoutes
(处理者):
定义处理请求的接口,通常包含一个处理方法(handle
),其具体实现方(ConcreteHandler
)实现处理请求的方式。每个处理者对象中通常会包含一个指向下一个处理者的引用(后继者)。
(2) CombineHandlers
(具体处理者):
实现 IRoutes
接口,处理请求的具体逻辑。如果自己能够处理请求,则处理;否则将请求传递给下一个处理者。当然,也可以设置拦截请求,将请求只在本层进行处理,不传递给下一层责任方进行处理。
(3) Client
(客户端):
负责创建和提交请求对象。按照指定的顺序构建责任链,可以设置拦截器,用于拦截请求,最后将请求发送到链的起始点。
下面是对上图各层次调用关系的描述:
图 32 责任链Next处理业务图
图 33 责任链Abort拦截业务图
在上图的基础上,下面对各个模块的代码进行深入剖析:
图 34 责任链客户端代码
图 35 客户端指定处理请求的中间件代码
执行流程:
图 36 IRoutes接口
图 37 GET方法代码
代码位置:routergroup.go的116-118行
图 38 具体处理者代码
代码位置:routergroup.go的86-91行
图 39 具体处理者真正构建责任链代码
代码位置:routergroup.go的241-248行
图 40 责任链的数据结构
代码位置:gin.go的54行
图 41 请求处理者的定义
代码位置:gin.go的48行
图 42 责任链访问下一个责任方Next()代码
代码位置:context.go的182-188行
图43 定义拦截索引
代码位置:context.go的50-51行
图 44 请求处理者设置拦截器
代码位置:context.go的199-201行
代码解释:
c.index
是 Context
结构体中的一个字段,用于跟踪当前执行的中间件或处理函数的位置。
abortIndex
是一个常量或全局变量,用于表示中止处理流程的索引值。
Abort()
方法将 c.index
设置为 abortIndex
,这样在接下来调用 Next()
方法时,循环将直接结束,不再执行后续的处理函数或中间件。
图 45 判断请求处理者是否设置拦截
代码位置:context.go的191-193行
责任链模式案例及调试分析
责任链模式案例编写如下:
下面分析一下每个部分的功能和调用流程:
结构定义和接口:
图101 定义Handler接口
Handler
接口:
Handle(c *gin.Context)
方法用于处理请求。
SetNext(handler Handler)
方法用于设置下一个责任链节点。
图102 定义Middleware中间件
Middleware
结构体:实现了 Handler 接口。
图103 定义中间件1的Handle方法
Handle(c *gin.Context)
方法中,打印 “M1 接收请求”,然后调用下一个处理者(如果存在),最后打印 “M1 得到响应”。
图104 定义中间件2的Handle方法
Handle(c *gin.Context)
方法中,打印 “M2 接收请求”,然后调用下一个处理者(如果存在),最后打印 “M2 得到响应”。
图105 定义末端中间件的Handle方法
FinalHandler
结构体:作为最终的处理者,实现了 Handler 接口。
Handle(c *gin.Context)
方法中,打印 “FinalHandler 接收请求”,然后调用具体的业务逻辑函数 Home(c)
,最后打印 “FinalHandler 得到响应”。
图106 定义视图层代码
Home
视图层部分:
图107 客户端构建责任链
图 108 成功启动责任链模式案例
责任链模式测试结果
APIfox测试工具监听向8080端口发送GET请求:显示Home Reciving……
,说明责任链构建成功,且将信息Home Reciving……
正确显示到客户端。
图132 Apifox发起GET测试请求
责任链模式测试结果进一步剖析如下:
图133 责任链模式测试结果剖析图
客户端构建责任链并发起监听8080端口请求,接下来分析控制台输出的顺序是否与调试分析的预测一致:
图134 Apifox发起GET请求
访问 http://localhost:8080/
,向服务端发出一条GET请求,可以看到以下控制台输出:
图135服务端监听端口多次测试请求
图 136 进行请求的拦截
图137 客户端发起GET请求
图138 服务端监听端口输出信息
结语
往期好文💕
保姆级教程
【保姆级教程】Windows11下go-zero的etcd安装与初步使用
【保姆级教程】Windows11安装go-zero代码生成工具goctl、protoc、go-zero
【Go-Zero】手把手带你在goland中创建api文件并设置高亮
报错解决
【Go-Zero】Error: user.api 27:9 syntax error: expected ‘:‘ | ‘IDENT‘ | ‘INT‘, got ‘(‘ 报错解决方案及api路由注意事项
【Go-Zero】Error: only one service expected goctl一键转换生成rpc服务错误解决方案
【Go-Zero】【error】 failed to initialize database, got error Error 1045 (28000):报错解决方案
【Go-Zero】Error 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)报错解决方案
【Go-Zero】type mismatch for field “Auth.AccessSecret“, expect “string“, actual “number“报错解决方案
【Go-Zero】Error: user.api 30:2 syntax error: expected ‘)‘ | ‘KEY‘, got ‘IDENT‘报错解决方案
【Go-Zero】Windows启动rpc服务报错panic:context deadline exceeded解决方案
Go面试向
【Go面试向】defer与time.sleep初探
【Go面试向】defer与return的执行顺序初探
【Go面试向】Go程序的执行顺序
【Go面试向】rune和byte类型的认识与使用
【Go面试向】实现map稳定的有序遍历的方式