Go-Web框架中AOP方案的实现方式

 更新时间:2023年06月05日 11:35:00   作者:今天捡到一百块钱  
本文主要介绍了Go-Web框架中AOP方案的实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

写在前面

最近不是在跟兔兔的七天系列嘛,目前是跟到了Web框架(好吧,这才是刚开始)。关于Web框架这一块,兔兔的文章是跟完了,也做完了,现在是在做总结。总结到AOP方案的时候,就有点蒙圈了,所以打算写下这篇文章记录总结两种AOP方案。

Gin的AOP实现方案

其实兔兔的AOP方案和Gin的AOP方案很相似。都是通过下标控制一个中间件进入到下一个中间件的。当下标大于中间件的个数的时候,整个中间件就会往回执行

image.png

特点

  • 中间件是是现在上下文中的
  • 通过下标进入下一个中间件

具体看下Gin的实现源码

image.png

具体看下兔兔的实现源码

image.png

其实是很类似的。对于这个方法,理解起来是没什么难度的。下面我就讲讲这个AOP方案的实现流程吧。

中间件注册是通过Use方法,这个方法是RouterGroup路由组提供的,在Gin中实际是抽象出了一个接口

image.png

image.png

2. 被注册的中间件是保存在路由组的属性中,上图中圈住的部分

3. 在ServerHTTP方法中匹配命中的路由视图函数符合条件的中间件

image.png

4. 将命中的视图函数添加到中间件列表中

image.png

5. 执行Next方法。每当中间件函数中有Next方法,就会再一次进入到Next方法,由于选取要执行的中间件是通过c.index控制的,每次进来都会自加1。当所有的中间件都执行完了,index的值就超过了中间件的个数。也就是退出了递归。递归最底层的方法都执行完成了,就开始一层一层返回了。

image.png

责任链制的AOP实现原理

对于责任链制的AOP方案,原理和洋葱模式是一样,(顺带提一下,Gin的设计模式叫做洋葱模式)。它的任务是一直构建"视图函数",最终构建成这样的形式

func m() {
   fmt.Println("coming middleware1...")
   func() {
      fmt.Println("coming middleware2...")
      func() {
         fmt.Println("coming middleware3...")
         func() {
            fmt.Println("coming middleware4...")
            func() {
               fmt.Println("coming middleware5...")
               func() {
               }()
               fmt.Println("outing middleware5...")
            }()
            fmt.Println("outing middleware4...")
         }()
         fmt.Println("outing middleware3...")
      }()
      fmt.Println("outing middleware2...")
   }()
   fmt.Println("outing middleware1...")
}

但是上述这种形式太不优雅了,我们就使用一个责任链的设计模式来实现、优化,但是精髓就是构建出这种样子。

image.png

注意

  • 我们需要对中间件进行一个包装,就是说对中间件的函数签名进行一个包装
  • 我们的视图函数不用变
  • 可以理解的是中间件函数就是生成一个视图函数,只不过生成的视图函数嵌入了一些别的通用逻辑
// 视图函数签名
type HandleFunc func(ctx *Context)
// 中间件函数签名
type Middleware func(next HandleFunc) HandeFunc

下文我统一将中间函数和命中的视图函数叫做中间件。不过命中的视图函数会加上特殊二字

中间件函数签名解释一下:

  • 参数next是下一次需要的中间件逻辑
  • 返回值是一个特殊的中间件,这个就是当前这个中间件的逻辑

具体的一个中间件示例代码

func Logger() Middleware {
   return func(next HandleFunc) HandleFunc {
       return func(ctx *Context){
           fmt.Println("请求来了")
           next(ctx)
           fmt.Println("请求走了")
       }
   }
}

image.png

解释示例代码:

  • Logger函数返回一个Middleware函数。返回一个视图函数构造器
  • fmt.Println("请求来了")fmt.Println("请求走了")两行代码分别嵌在next下一个需要执行的中间件逻辑

上述已经讲完了关于责任链制的AOP方法的具体原理。但是到这里还不够,这只是原理,还没有和我们的框架进行适配。接下来就具体讲讲怎么和咱们的框架进行适配。

责任链制的AOP方案应用

首先还是需要定义好视图函数、中间件函数的签名

// 视图函数签名
type HandleFunc func(ctx *Context)
// 中间件函数签名
type Middleware func(next HandleFunc) HandeFunc

我们的AOP是集成在server层面上的,在Gin中,AOP是集成在Context上下文层面上面的。其实这个没有多大的区别的,无非是设计者的设计思想而已。

说我们的AOP是集成在server层面其实还不太准确,准确来说是在路由组RouterGroup上的。

路由组RouterGroup定义一个属性保存当前组的所有中间件

image.png

2. 路由组RouterGroup提供一个方法Use注册中间件

image.png

3. 匹配路由的时候需要找出当前路由所属哪个组,并将其所有的中间件抽离出来

image.png

4. 组装中间件

在组装中间价的时候,我们需要注意:

  • 我们注册的中间件是有顺序的
  • 我们执行的中间件也是要有顺序的
  • 先注册先执行前半部分

image.png

基于上述的注意事项,我们组装的中间件应该是从后往前组装的。这里需要花点时间想想

我们可以这样想,如果是按照正向的顺序遍历middlewares的话,最后的handler应该是最后一个注册的中间件才对。这和我们的期待是完全相反的,从这也就能解释为什么我们需要从后往前组装中间件了。只有这样,最后handler才是我们第一个注册的中间件方法。

最后就执行handler方法即可。

image.png

总结

  • 基于洋葱模型的AOP方案和基于责任链制的AOP方案本质没有区别
  • Gin的AOP是集成在上下文中,我们的是集成在RouterGroup上。两种方式没有区别

 到此这篇关于Go-Web框架中AOP方案的实现方式的文章就介绍到这了,更多相关Go AOP实现内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang字符串的拼接方法汇总

    Golang字符串的拼接方法汇总

    字符串拼接在日常开发中是很常见的需求,今天我们来探讨下如何用golang来实现字符串的拼接
    2018-10-10
  • Golang搭建开发环境的图文教程

    Golang搭建开发环境的图文教程

    这篇文章主要介绍了Golang搭建开发环境,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • 解决Golang中ResponseWriter的一个坑

    解决Golang中ResponseWriter的一个坑

    这篇文章主要介绍了解决Golang中ResponseWriter的一个坑,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Go高级特性探究之对象比较详解

    Go高级特性探究之对象比较详解

    在go语言中,要比较两个对象是否完全相同,我们可以使用三种方法,这篇文章主要为大家介绍了这三种方法的具体实现,需要的可以参考一下
    2023-06-06
  • Golang开发gRPC服务入门介绍

    Golang开发gRPC服务入门介绍

    这篇文章主要介绍了Golang开发gRPC服务,Golang开发gRPC应用程序的套路也已经很清晰,这篇文章就来做一个简单的介绍,算是入门,需要的朋友可以参考下
    2022-04-04
  • Golang token的生成和解析详解

    Golang token的生成和解析详解

    这篇文章主要给大家介绍了Golang token的生成和解析,文中通过代码示例给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-02-02
  • wind10 idea中 go 开发环境搭建教程图解

    wind10 idea中 go 开发环境搭建教程图解

    这篇文章主要介绍了wind10 idea中 go 开发环境搭建过程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • Go语言实现图片快递信息识别的简易方法

    Go语言实现图片快递信息识别的简易方法

    这篇文章主要为大家介绍了Go语言实现图片快递信息识别的简易方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • golang 数组随机排序的实现

    golang 数组随机排序的实现

    本文主要介绍了golang 数组随机排序的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • Go语言转化php数组的示例代码

    Go语言转化php数组的示例代码

    这篇文章主要为大家详细介绍了Go语言如何实现转化php数组的相关知识,文中的示例代码讲解详细,对我们深入学习GO语言有一定的帮助,需要的可以参考下
    2023-11-11

最新评论