【Gin】智慧之光:Gin框架中装饰器模式的精湛运用与技术深度解析(下)

4 篇文章 0 订阅

【Gin】智慧之光:Gin框架中装饰器模式的精湛运用与技术深度解析(下)

大家好 我是寸铁👊
【Gin】智慧之光:Gin框架中装饰器模式的精湛运用与技术深度解析(下)✨
喜欢的小伙伴可以点点关注 💝

在这里插入图片描述

前言

本次文章分为上下两部分,上部分为对理论的介绍,下部分为具体的底层代码深度剖析和编程实践,感兴趣的伙伴不要错过哦~

在现代软件开发的迅猛发展中,装饰器模式作为一种优雅而强大的设计模式,被广泛应用于构建灵活、可扩展的代码结构。尤其是在Gin框架这样的高性能Web应用框架中,合理运用装饰器模式能够有效地增强代码的复用性和可维护性,从而提升开发效率和系统的整体可靠性。本文将深入探讨装饰器模式在Gin框架中的战略性应用与技术深度,帮助开发者全面理解如何利用装饰器模式优化和增强其应用程序的架构。
装饰器模式通过动态地将责任附加到对象上,实现了功能的增强,而无需修改现有代码结构。在Gin框架中,装饰器模式可以被应用于路由、中间件以及HTTP处理器等关键组件,使其能够更加灵活地适应不断变化的业务需求和功能扩展。本文旨在为开发者提供深入的技术见解和实用的应用指南,帮助他们充分利用装饰器模式的潜力,打造出更加健壮和可维护的Gin框架应用程序。

装饰器模式

主程序的流程

由下图48可得:程序开始,客户端先创建路由处理器Handler,再创建装饰器ConcreteDecorator。接着,使用装饰器调用Use方法添加Handler engine对象,起到装饰engine引擎对象的作用,在获得装饰好后的engine引擎对象后,使用engine引擎对象进行相关的业务处理,engine引擎对象处理业务完毕后,程序结束。
在这里插入图片描述

图 48 装饰器模式主程序流程图


程序模块之间的调用关系

在这里插入图片描述

图 49 装饰器模式程序调用图

由上图49可得:
gin.Logger()gin.Recovery() gin.ErrorLogger() 是 Gin 框架中的中间件函数,它们典型地用于实现装饰器模式。在这个模式中,通常涉及以下角色:
组件接口 (Component Interface):
在 Gin 中,这通常是一个 HTTP 请求处理器(handler),例如 func(c *gin.Context) 这样的函数,它们负责处理特定的 HTTP 请求并生成响应。
具体组件 (Concrete Component)
在你的例子中,r.GET(“/ping”, func(c *gin.Context) { … }) 中的匿名函数是具体组件的实例。它实现了处理 /ping 路径的请求,并返回一个 JSON 响应。
装饰器接口 (Decorator Interface):
在 Gin 框架中,中间件函数就是装饰器接口的具体实现。例如,gin.Logger()gin.Recovery() gin.ErrorLogger(),它们都允许在请求处理前后执行额外的逻辑。
具体装饰器 (Concrete Decorator):
具体装饰器是实现了装饰器接口的具体函数。在你的代码中,.Use(gin.Logger()).Use(gin.Recovery()) .Use(gin.ErrorLogger())分别将这些具体装饰器应用于 Gin 引擎 r。
客户端 (Client):
在 Gin 框架中,客户端就是通过 HTTP 请求来调用具体组件的实体。在你的例子中,客户端可能是通过发送 HTTP GET 请求 /ping 来触发处理函数的执行。

由上图49可得:
程序调用顺序如下:
客户端使用Gin引擎对象r,调用Use方法,不断使用gin的中间件函数像gin.Logger()gin.Recovery()这类中间件函数装饰引擎对象r。像gin.Logger()gin.Recovery()这类中间件函数本质都是Handlerfunc类型,是func类型的别名类型。而究其本质是Gin引擎对象r聚合了一个RouterGroup对象,这个对象是一个Handlerfunc数组,可以不断往该数组对象中添加中间件函数,不断装饰Gin引擎对象r,最后再调用returnObj()方法将装饰好的engine对象返回给客户端。


在这里插入图片描述

图 Use装饰器模型图

在上图的基础上,下面对各个模块的代码进行深入剖析:
在这里插入图片描述

图50 装饰器模式的Use方法

代码位置:gin.go的312-317行
312行:Use Engine结构体的一个方法。它接受一个或多个 HandlerFunc 类型的中间件函数作为参数,并返回IRoutes接口。
313行:调用 RouterGroup 结构体的 Use 方法,将传入的中间件函数 middleware 应用到当前的路由组中。RouterGroup 是 Engine 结构体中的一个字段,它可能表示一个路由分组或者路由器实例。Use 方法的作用是将中间件函数应用到路由组中,用于处理路由请求之前或之后的逻辑。
314行:调用 engine 结构体的rebuild404Handlers方法。rebuild404Handlers 方法的具体实现在上下文中未提供,但根据命名推测,它可能用于重新构建处理 404 错误的处理函数集合。这种情况下,通常是为了在添加中间件后,重新设置路由器或路由组的 404 错误处理逻辑。
315行:调用engine结构体的 rebuild405Handlers 方法。它可能用于重新构建处理 405 错误(HTTP 方法不允许)的处理函数集合。这样做通常是为了确保在添加中间件后,路由器或路由组能够正确地处理 HTTP 方法不允许的情况。
316行:返回当前的 engine 对象,类型为 IRoutes 接口。


RouterGroup调用的Use方法,用于不断装饰engine 对象,代码剖析如下:
在这里插入图片描述

图 51 RouterGroup的Use()方法

代码位置:routergroup.go的65-68行
65行:Use 是 RouterGroup 结构体的一个方法。它接受一个或多个 HandlerFunc 类型的中间件函数作为参数,并返回 IRoutes 接口。
66行:将传入的中间件函数middleware添加到 Handlers 切片中。Handlers RouterGroup结构体中的一个字段,通常用于存储中间件函数。通过 append 函数,将传入的中间件函数追加到 Handlers 切片的末尾。
67行:调用group.returnObj()方法,并返回其结果。returnObj() 方法的具体实现在上下文中未提供,返回一个 IRoutes 接口类型的对象。通过返回 returnObj() 方法的结果,实现了方法链式调用的模式。

RouterGroup实现IRoutes接口的Use方法,接口的方法如下:
代码位置:routegroup.go的34行
在这里插入图片描述

图52 IRoutes接口代码

调用returnObj()方法将装饰好的engine对象返回给客户端使用
代码位置:routegroup.go的254-259行
在这里插入图片描述

图53 装饰器模式returnObj代码

代码解释:定义了一个方法 returnObj(),它属于类型为 RouterGroup 的接收器。定义了一个方法 returnObj(),它返回一个实现了 IRoutes 接口的对象。如果 group.root 的值为真(即为 true),则返回 group.engine。这里假设group.engine是一个实现了 IRoutes 接口的对象。如果 group.root 不为真,则直接返回 group 本身。
究其本质,为什么可以不断地进行装饰,不断调用Use方法进行装饰?本质上是因为对象类型均为func的别名类型HandleFunc。再次回到312行位置:

在这里插入图片描述

图54 Use方法声明
发现Use的对象类型均为HandlerFunc:
在这里插入图片描述

图 55 HandlerFunc函数说明

而在RouterGroup结构体中的Handlers这个处理器集合链,类型也为HandlerFunc,因此,才可以实现不断装饰的效果。
代码位置:gin.go 56行
在这里插入图片描述

图56 RouterGroup结构体代码

代码位置:gin.go 54行
在这里插入图片描述

图57 HandlerFunc类型声明


装饰器模式案例及调试分析

装饰器模式是一种结构型设计模式,它允许你通过将对象包装在装饰器类的实例中来动态地扩展其行为。这种模式可以在不修改现有对象结构的情况下,添加功能或责任。

(1) 装饰器模式案例如下:
在这里插入图片描述

图109 装饰器模式的客户端

说明: 创建了一个新的 Gin 引擎实例 r。调用WithCustomMiddlewares 装饰器函数,接受一个 *gin.Engine 参数并返回修改后的 *gin.Engine。它的作用是向 Gin 引擎不断装饰自定义的中间件,如日志记录、恢复机制等。在 /decorator 路径上定义了一个 GET 请求的处理函数。当请求到达这个路径时,返回一个 JSON 响应,内容为 { "message": "Decorating Successfully" }。启动 Gin 服务,监听端口 8886。这会使得 Gin 应用开始接受来自该端口的 HTTP 请求。


在这里插入图片描述

图110添加自定义中间件

WithCustomMiddlewares 是一个函数,接受一个 *gin.Engine 参数 engine,并返回修改后的同一类型 *gin.Engine
在函数内部,通过 engine.Use() 方法依次对engine装饰器对象装饰了三种 Gin 框架的中间件:
gin.LoggerWithFormatter:这是一个自定义格式的日志中间件,用于记录每个请求的详细信息,包括请求时间、HTTP 方法、路径、请求延迟、客户端 IP 和可能的错误信息。
gin.Recovery():这是 Gin 框架提供的恢复中间件,用于在发生 panic 时恢复应用程序,防止程序崩溃并返回 500 错误。
gin.ErrorLogger():这是 Gin 框架的错误日志中间件,用于记录请求处理过程中的错误信息。
返回修改后的 engine:
最后,函数返回已经添加了自定义中间件的engine对象,这样调用 WithCustomMiddlewares 的代码就能够使用这些中间件来处理 HTTP 请求。

(2) 调试分析:
启动测试案例的服务端,完成对象的装饰,并等待客户端请求的发送。运行测试装饰器模式案例成功!
在这里插入图片描述

图111 启动装饰器模式案例成功

使用API测试工具APIfox,向服务器监听的端口发送GET请求,并得到服务端发送的响应信息,调试装饰器模式案例成功!
在这里插入图片描述

图112 Apifox发起GET请求


装饰器模式测试结果

客户端使用API测试工具APIfox,向服务器监听的端口发送GET请求,并得到服务端发送的响应信息,测试装饰器模式案例成功!
在这里插入图片描述

图139装饰器模式发起GET请求

观察服务端的监控信息,验证是否按照编写的案例,将装饰好对象的信息显示出来,预计会输出如下图红框类似的信息(即请求时间、HTTP 方法、路径、请求延迟、客户端 IP 和可能的错误信息)。

在这里插入图片描述

图140自定义中间件方法

服务端接收客户端请求信息后在控制台显示信息如下:
[2024-06-27 15:25:10] | GET | /decorator | 547.9µs | 127.0.0.1 |
说明:请求时间、HTTP 方法、路径、请求延迟、客户端 IP 和可能的错误信息
与上面的预期结果一样,输出相关的日志器信息,说明装饰对象成功,装饰器模式案例测试完毕!

在这里插入图片描述

图141测试结果分析图

结语

本次文章分为上下两部分,上部分为对理论的介绍,下部分为具体的底层代码深度剖析和编程实践,感兴趣的伙伴不要错过哦~

通过本文的探讨,我们详细分析了装饰器模式在Gin框架中的应用场景和实现策略。装饰器模式不仅能够优雅地解决代码中的功能扩展问题,还能够提升系统的灵活性和可扩展性,使开发者能够更加高效地应对复杂的业务需求和技术挑战。在实际项目中,合理运用装饰器模式能够有效地降低代码的耦合度,增强代码的可重用性和可维护性,从而为Gin框架应用的长期发展奠定坚实的技术基础。希望本文能够为广大开发者提供有益的参考和实用的指导,帮助他们在实际应用中充分发挥装饰器模式的优势,构建出更加强大和灵活的软件系统。


看到这里的小伙伴,恭喜你又掌握了一个技能👊
希望大家能取得胜利,坚持就是胜利💪
我是寸铁!我们下期再见💕


在这里插入图片描述

往期好文💕

保姆级教程

【保姆级教程】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稳定的有序遍历的方式

  • 21
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寸 铁

感谢您的支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值