欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go-Web框架中AOP方案的實(shí)現(xiàn)方式

 更新時間:2023年06月05日 11:35:00   作者:今天撿到一百塊錢  
本文主要介紹了Go-Web框架中AOP方案的實(shí)現(xiàn)方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

寫在前面

最近不是在跟兔兔的七天系列嘛,目前是跟到了Web框架(好吧,這才是剛開始)。關(guān)于Web框架這一塊,兔兔的文章是跟完了,也做完了,現(xiàn)在是在做總結(jié)。總結(jié)到AOP方案的時候,就有點(diǎn)蒙圈了,所以打算寫下這篇文章記錄總結(jié)兩種AOP方案。

Gin的AOP實(shí)現(xiàn)方案

其實(shí)兔兔的AOP方案和Gin的AOP方案很相似。都是通過下標(biāo)控制一個中間件進(jìn)入到下一個中間件的。當(dāng)下標(biāo)大于中間件的個數(shù)的時候,整個中間件就會往回執(zhí)行

image.png

特點(diǎn)

  • 中間件是是現(xiàn)在上下文中的
  • 通過下標(biāo)進(jìn)入下一個中間件

具體看下Gin的實(shí)現(xiàn)源碼

image.png

具體看下兔兔的實(shí)現(xiàn)源碼

image.png

其實(shí)是很類似的。對于這個方法,理解起來是沒什么難度的。下面我就講講這個AOP方案的實(shí)現(xiàn)流程吧。

中間件注冊是通過Use方法,這個方法是RouterGroup路由組提供的,在Gin中實(shí)際是抽象出了一個接口

image.png

image.png

2. 被注冊的中間件是保存在路由組的屬性中,上圖中圈住的部分

3. 在ServerHTTP方法中匹配命中的路由視圖函數(shù)符合條件的中間件。

image.png

4. 將命中的視圖函數(shù)添加到中間件列表中

image.png

5. 執(zhí)行Next方法。每當(dāng)中間件函數(shù)中有Next方法,就會再一次進(jìn)入到Next方法,由于選取要執(zhí)行的中間件是通過c.index控制的,每次進(jìn)來都會自加1。當(dāng)所有的中間件都執(zhí)行完了,index的值就超過了中間件的個數(shù)。也就是退出了遞歸。遞歸最底層的方法都執(zhí)行完成了,就開始一層一層返回了。

image.png

責(zé)任鏈制的AOP實(shí)現(xiàn)原理

對于責(zé)任鏈制的AOP方案,原理和洋蔥模式是一樣,(順帶提一下,Gin的設(shè)計模式叫做洋蔥模式)。它的任務(wù)是一直構(gòu)建"視圖函數(shù)",最終構(gòu)建成這樣的形式

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...")
}

但是上述這種形式太不優(yōu)雅了,我們就使用一個責(zé)任鏈的設(shè)計模式來實(shí)現(xiàn)、優(yōu)化,但是精髓就是構(gòu)建出這種樣子。

image.png

注意

  • 我們需要對中間件進(jìn)行一個包裝,就是說對中間件的函數(shù)簽名進(jìn)行一個包裝
  • 我們的視圖函數(shù)不用變
  • 可以理解的是中間件函數(shù)就是生成一個視圖函數(shù),只不過生成的視圖函數(shù)嵌入了一些別的通用邏輯
// 視圖函數(shù)簽名
type HandleFunc func(ctx *Context)
// 中間件函數(shù)簽名
type Middleware func(next HandleFunc) HandeFunc

下文我統(tǒng)一將中間函數(shù)和命中的視圖函數(shù)叫做中間件。不過命中的視圖函數(shù)會加上特殊二字

中間件函數(shù)簽名解釋一下:

  • 參數(shù)next是下一次需要的中間件邏輯
  • 返回值是一個特殊的中間件,這個就是當(dāng)前這個中間件的邏輯

具體的一個中間件示例代碼

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

image.png

解釋示例代碼:

  • Logger函數(shù)返回一個Middleware函數(shù)。返回一個視圖函數(shù)構(gòu)造器
  • fmt.Println("請求來了")fmt.Println("請求走了")兩行代碼分別嵌在next下一個需要執(zhí)行的中間件邏輯

上述已經(jīng)講完了關(guān)于責(zé)任鏈制的AOP方法的具體原理。但是到這里還不夠,這只是原理,還沒有和我們的框架進(jìn)行適配。接下來就具體講講怎么和咱們的框架進(jìn)行適配。

責(zé)任鏈制的AOP方案應(yīng)用

首先還是需要定義好視圖函數(shù)、中間件函數(shù)的簽名

// 視圖函數(shù)簽名
type HandleFunc func(ctx *Context)
// 中間件函數(shù)簽名
type Middleware func(next HandleFunc) HandeFunc

我們的AOP是集成在server層面上的,在Gin中,AOP是集成在Context上下文層面上面的。其實(shí)這個沒有多大的區(qū)別的,無非是設(shè)計者的設(shè)計思想而已。

說我們的AOP是集成在server層面其實(shí)還不太準(zhǔn)確,準(zhǔn)確來說是在路由組RouterGroup上的。

路由組RouterGroup定義一個屬性保存當(dāng)前組的所有中間件

image.png

2. 路由組RouterGroup提供一個方法Use注冊中間件

image.png

3. 匹配路由的時候需要找出當(dāng)前路由所屬哪個組,并將其所有的中間件抽離出來

image.png

4. 組裝中間件

在組裝中間價的時候,我們需要注意:

  • 我們注冊的中間件是有順序的
  • 我們執(zhí)行的中間件也是要有順序的
  • 先注冊先執(zhí)行前半部分

image.png

基于上述的注意事項(xiàng),我們組裝的中間件應(yīng)該是從后往前組裝的。這里需要花點(diǎn)時間想想

我們可以這樣想,如果是按照正向的順序遍歷middlewares的話,最后的handler應(yīng)該是最后一個注冊的中間件才對。這和我們的期待是完全相反的,從這也就能解釋為什么我們需要從后往前組裝中間件了。只有這樣,最后handler才是我們第一個注冊的中間件方法。

最后就執(zhí)行handler方法即可。

image.png

總結(jié)

  • 基于洋蔥模型的AOP方案和基于責(zé)任鏈制的AOP方案本質(zhì)沒有區(qū)別
  • Gin的AOP是集成在上下文中,我們的是集成在RouterGroup上。兩種方式?jīng)]有區(qū)別

 到此這篇關(guān)于Go-Web框架中AOP方案的實(shí)現(xiàn)方式的文章就介紹到這了,更多相關(guān)Go AOP實(shí)現(xiàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 快速掌握Go語言正/反向代理

    快速掌握Go語言正/反向代理

    這篇文章主要介紹了快速掌握Go語言正/反向代理的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • 使用dep 配置golang 開發(fā)環(huán)境的操作方法

    使用dep 配置golang 開發(fā)環(huán)境的操作方法

    下面小編就為大家?guī)硪黄褂胐ep 配置golang 開發(fā)環(huán)境的操作方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • 詳解Go語言如何解析帶注釋的json

    詳解Go語言如何解析帶注釋的json

    標(biāo)準(zhǔn)的json格式是不帶注釋,但是有時候?yàn)榱朔奖憷斫鈐son中各字段的含義,需要支持帶注釋的json,這篇文章主要介紹了Go語言解析帶注釋json的相關(guān)方法,希望對大家有所幫助
    2024-03-03
  • Go 實(shí)現(xiàn)英尺和米的簡單單位換算方式

    Go 實(shí)現(xiàn)英尺和米的簡單單位換算方式

    這篇文章主要介紹了Go 實(shí)現(xiàn)英尺和米的簡單單位換算方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • 從零封裝Gin框架實(shí)現(xiàn)日志初始化及切割歸檔功能

    從零封裝Gin框架實(shí)現(xiàn)日志初始化及切割歸檔功能

    這篇文章主要為大家介紹了從零封裝Gin框架實(shí)現(xiàn)日志初始化及切割歸檔功能示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Go泛型實(shí)戰(zhàn)教程之如何在結(jié)構(gòu)體中使用泛型

    Go泛型實(shí)戰(zhàn)教程之如何在結(jié)構(gòu)體中使用泛型

    這篇文章主要介紹了Go泛型實(shí)戰(zhàn)教程之如何在結(jié)構(gòu)體中使用泛型,根據(jù)Go泛型使用的三步曲提到的:類型參數(shù)化、定義類型約束、類型實(shí)例化我們一步步來定義我們的緩存結(jié)構(gòu)體,需要的朋友可以參考下
    2022-07-07
  • 使用GO操作MongoDB的方法

    使用GO操作MongoDB的方法

    這篇文章主要介紹了使用GO操作MongoDB,包括安裝MongoDB驅(qū)動程序連接mongodb的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • Go語言學(xué)習(xí)之Switch語句的使用

    Go語言學(xué)習(xí)之Switch語句的使用

    這篇文章主要通過一些示例為大家介紹一下Go語言中Switch語句的基本語法以及使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-06-06
  • go panic時如何讓函數(shù)返回數(shù)據(jù)?

    go panic時如何讓函數(shù)返回數(shù)據(jù)?

    今天小編就為大家分享一篇關(guān)于go panic時如何讓函數(shù)返回數(shù)據(jù)?,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • Golang Slice和map的坑

    Golang Slice和map的坑

    Golang中的Slice和Map在內(nèi)存空間上,有一些不同,本文主要介紹了Golang Slice和map的坑,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-04-04

最新評論