中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

做電商網(wǎng)站賺錢(qián)嗎關(guān)鍵詞排名優(yōu)化顧問(wèn)

做電商網(wǎng)站賺錢(qián)嗎,關(guān)鍵詞排名優(yōu)化顧問(wèn),手機(jī)上的網(wǎng)站,軟件開(kāi)發(fā)專業(yè)有哪些【Gin】深度解析:在Gin框架中優(yōu)化應(yīng)用程序流程的責(zé)任鏈設(shè)計(jì)模式(下) 大家好 我是寸鐵👊 【Gin】深度解析:在Gin框架中優(yōu)化應(yīng)用程序流程的責(zé)任鏈設(shè)計(jì)模式(下)? 喜歡的小伙伴可以點(diǎn)點(diǎn)關(guān)注 💝 前言 本次文章分為上下兩部分&#xf…

【Gin】深度解析:在Gin框架中優(yōu)化應(yīng)用程序流程的責(zé)任鏈設(shè)計(jì)模式(下)

大家好 我是寸鐵👊
【Gin】深度解析:在Gin框架中優(yōu)化應(yīng)用程序流程的責(zé)任鏈設(shè)計(jì)模式(下)?
喜歡的小伙伴可以點(diǎn)點(diǎn)關(guān)注 💝

在這里插入圖片描述


前言

本次文章分為上下兩部分,上部分為對(duì)理論的介紹,下部分為具體的底層代碼深度剖析和編程實(shí)踐,感興趣的伙伴不要錯(cuò)過(guò)哦~

責(zé)任鏈設(shè)計(jì)模式作為一種經(jīng)典的行為設(shè)計(jì)模式,在現(xiàn)代軟件開(kāi)發(fā)中扮演著重要角色。特別是在高效的Web應(yīng)用開(kāi)發(fā)中,如Gin框架這樣的輕量級(jí)Go語(yǔ)言Web框架,合理地應(yīng)用責(zé)任鏈模式可以顯著提升代碼的可擴(kuò)展性和靈活性。本文將深入探討在Gin框架中責(zé)任鏈模式的實(shí)現(xiàn)原理、優(yōu)化策略以及實(shí)際應(yīng)用場(chǎng)景。
責(zé)任鏈模式通過(guò)將請(qǐng)求的發(fā)送者和接收者解耦,將多個(gè)對(duì)象連成一條鏈,并在鏈上傳遞請(qǐng)求,直到有對(duì)象處理該請(qǐng)求為止。在Gin框架中,利用責(zé)任鏈模式可以有效地處理請(qǐng)求的流程控制、中間件管理和異常處理,使得代碼結(jié)構(gòu)更加清晰和可維護(hù)。本文將探索如何在Gin框架中設(shè)計(jì)和優(yōu)化責(zé)任鏈模式,以提升應(yīng)用程序的性能和可維護(hù)性。


關(guān)鍵的類圖和時(shí)序圖

(1)類圖
責(zé)任鏈模式包含以下幾個(gè)主要角色:
Handler(抽象處理者):
聲明一個(gè)處理請(qǐng)求的接口,通常包含一個(gè)指向下一個(gè)處理者的引用。

MiddlerWare(具體處理者):
Gin的中間件實(shí)現(xiàn)抽象處理者的處理方法,并根據(jù)自身的處理能力決定是否處理請(qǐng)求,如果不能處理則將請(qǐng)求傳遞給下一個(gè)處理者。

Client(客戶端):
創(chuàng)建一個(gè)具體處理者對(duì)象的鏈,并向鏈上的第一個(gè)處理者對(duì)象發(fā)送請(qǐng)求。


在這里插入圖片描述

圖 28 責(zé)任鏈模式類圖

由類圖28可得:先聲明一個(gè)處理請(qǐng)求的接口Handler,通常聚合一個(gè)指向下一個(gè)處理者的引用successor。聲明處理請(qǐng)求的方法handlerRequest(),由具體的中間件責(zé)任方MiddleWare實(shí)現(xiàn)。接著Gin的中間件實(shí)現(xiàn)抽象處理者的處理方法,調(diào)用handlerRequest()方法根據(jù)自身的處理能力決定是否處理請(qǐng)求,如果不能處理則將請(qǐng)求傳遞給下一個(gè)處理者nextHandler??蛻舳藙?chuàng)建一個(gè)具體處理者對(duì)象的鏈,并向鏈上的第一個(gè)處理者對(duì)象發(fā)送請(qǐng)求。


(2)時(shí)序圖

在這里插入圖片描述

圖 29 責(zé)任鏈模式時(shí)序圖

由上圖29可得:客戶端發(fā)送請(qǐng)求:客戶端調(diào)用具體處理者鏈的第一個(gè)處理者的handleRequest()方法,將請(qǐng)求request傳遞給鏈的起始點(diǎn)MiddleWare1
責(zé)任鏈中的處理者Midlleware處理請(qǐng)求:每個(gè)具體中間件處理者Midlleware收到請(qǐng)求后,根據(jù)自己的處理能力決定是否處理請(qǐng)求。
請(qǐng)求傳遞到合適的處理者:如果當(dāng)前處理者能夠處理請(qǐng)求,則處理完成;如果不能處理,則將請(qǐng)求傳遞給鏈中的下一個(gè)處理者Midlleware。
鏈的末端處理:請(qǐng)求request會(huì)沿著鏈依次傳遞,直到被處理或者到達(dá)鏈的末端。如果末端處理者能夠處理請(qǐng)求processing Request,則處理完成后,沿著責(zé)任鏈返回處理完后的響應(yīng)信息response`。如果整個(gè)鏈上的處理者都不能處理請(qǐng)求,則請(qǐng)求最終未被處理。


主程序的流程

由下圖30可知:一開(kāi)始,Client客戶端構(gòu)建責(zé)任鏈后,開(kāi)始發(fā)起請(qǐng)求,責(zé)任鏈的中間件MiddleWare1開(kāi)始接收請(qǐng)求,然后處理請(qǐng)求,處理完畢后,返回響應(yīng)給上層調(diào)用者,如果客戶端接收到響應(yīng)后,則程序退出。
接著如果責(zé)任鏈的中間件MiddleWare1無(wú)法處理請(qǐng)求,則將請(qǐng)求傳遞給下一層中間件MiddleWare2MiddleWare2處理請(qǐng)求,處理完畢后,返回響應(yīng)給上層調(diào)用者,再由上層調(diào)用者沿責(zé)任鏈繼續(xù)將響應(yīng)信息返回給上層調(diào)用者,直至Client客戶端。
如果責(zé)任鏈的中間件MiddleWare2無(wú)法處理請(qǐng)求,則將請(qǐng)求傳遞給下一層中間件MiddleWare……MiddleWare……處理請(qǐng)求,處理完畢后,返回響應(yīng)給上層調(diào)用者,再由上層調(diào)用者沿責(zé)任鏈繼續(xù)將響應(yīng)信息返回給上層調(diào)用者,直至Client客戶端。
如果責(zé)任鏈的中間件都無(wú)法處理請(qǐng)求,則將請(qǐng)求傳遞給最后一層中間件FinalMiddleWare處理請(qǐng)求,處理完畢后,返回響應(yīng)給上層調(diào)用者,再由上層調(diào)用者沿責(zé)任鏈繼續(xù)將響應(yīng)信息返回給上層調(diào)用者,直至Client客戶端。如果最后一層中間件FinalMiddleWare都無(wú)法處理請(qǐng)求,則責(zé)任鏈程序結(jié)束退出。

在這里插入圖片描述

圖 30 責(zé)任鏈模式主程序流程圖

程序模塊之間的調(diào)用關(guān)系

下圖為程序各模塊之間的調(diào)用關(guān)系:

在這里插入圖片描述

圖 31 責(zé)任鏈模式程序模塊調(diào)用圖
由上圖31可知,責(zé)任鏈模式主要有如下3個(gè)角色:
(1) IRoutes(處理者):
定義處理請(qǐng)求的接口,通常包含一個(gè)處理方法(handle),其具體實(shí)現(xiàn)方(ConcreteHandler)實(shí)現(xiàn)處理請(qǐng)求的方式。每個(gè)處理者對(duì)象中通常會(huì)包含一個(gè)指向下一個(gè)處理者的引用(后繼者)。


(2) CombineHandlers(具體處理者):
實(shí)現(xiàn) IRoutes接口,處理請(qǐng)求的具體邏輯。如果自己能夠處理請(qǐng)求,則處理;否則將請(qǐng)求傳遞給下一個(gè)處理者。當(dāng)然,也可以設(shè)置攔截請(qǐng)求,將請(qǐng)求只在本層進(jìn)行處理,不傳遞給下一層責(zé)任方進(jìn)行處理。


(3) Client(客戶端):
負(fù)責(zé)創(chuàng)建和提交請(qǐng)求對(duì)象。按照指定的順序構(gòu)建責(zé)任鏈,可以設(shè)置攔截器,用于攔截請(qǐng)求,最后將請(qǐng)求發(fā)送到鏈的起始點(diǎn)。


下面是對(duì)上圖各層次調(diào)用關(guān)系的描述:

客戶端調(diào)用r.GET進(jìn)行按照指定的順序構(gòu)建責(zé)任鏈,GET方法實(shí)現(xiàn)IRoutes接口,GET方法將構(gòu)建路由組對(duì)象的請(qǐng)求轉(zhuǎn)發(fā)給真正的構(gòu)建路由組對(duì)象的handle方法,該handle方法實(shí)現(xiàn)IRoutes接口。handle方法進(jìn)一步轉(zhuǎn)發(fā)構(gòu)建GET中指定順序的中間件責(zé)任鏈請(qǐng)求給具體處理者CombineHandlers,具體處理者CombineHandlers負(fù)責(zé)按照客戶端指定的順序構(gòu)建中間件責(zé)任鏈。責(zé)任鏈中的每一個(gè)處理者存在Next()Abort()方法,調(diào)用Next()方法遍歷責(zé)任鏈中的請(qǐng)求者對(duì)象,依次將請(qǐng)求傳遞給鏈中的具體處理者對(duì)象業(yè)務(wù)圖見(jiàn)下圖32。Abort()方法設(shè)置索引為超出合法范圍的值,使得不將請(qǐng)求轉(zhuǎn)發(fā)給下一個(gè)處理者,實(shí)現(xiàn)攔截效果,業(yè)務(wù)圖見(jiàn)下圖33。構(gòu)建完后返回給上層的調(diào)用者HandlerHandler將路由組對(duì)象組裝好后,再將組裝好的路由組對(duì)象返回給GET方法,GET方法返回嵌入責(zé)任處理鏈的路由組對(duì)象給客戶端(責(zé)任鏈的起始點(diǎn))進(jìn)行調(diào)用,客戶端拿到對(duì)象后,做下一步的處理。

在這里插入圖片描述

圖 32 責(zé)任鏈Next處理業(yè)務(wù)圖

在這里插入圖片描述

圖 33 責(zé)任鏈Abort攔截業(yè)務(wù)圖

在上圖的基礎(chǔ)上,下面對(duì)各個(gè)模塊的代碼進(jìn)行深入剖析:
在這里插入圖片描述

圖 34 責(zé)任鏈客戶端代碼

gin.Default() 創(chuàng)建了一個(gè)默認(rèn)的 Gin 路由引擎實(shí)例 r。
r.GET("", middleWare1, middleWare2, Home) 定義了一個(gè) GET 請(qǐng)求的路由,其中 middleWare1 middleWare2 是中間件函數(shù),用于在請(qǐng)求到達(dá)最終處理函數(shù) Home 之前執(zhí)行預(yù)處理或者其他操作。
r.Run(":8080") 啟動(dòng)了 HTTP 服務(wù)器,監(jiān)聽(tīng)在 8080 端口上。

在這里插入圖片描述

圖 35 客戶端指定處理請(qǐng)求的中間件代碼

函數(shù)簽名和參數(shù):
func middleWare1(c *gin.Context):這是一個(gè)函數(shù)簽名,接收一個(gè) *gin.Context 類型的參數(shù) c,用于處理 HTTP 請(qǐng)求和響應(yīng)。
處理邏輯:fmt.Println("M1 請(qǐng)求部分"):這行代碼輸出 “M1 請(qǐng)求部分”,表示這是中間件處理請(qǐng)求的部分,可以在這里執(zhí)行一些預(yù)處理邏輯,如日志記錄、權(quán)限檢查等。
c.Next()
c.Next() 是 Gin 框架中用于將控制傳遞給鏈中的下一個(gè)處理程序的方法。在這里,它表示將控制權(quán)傳遞給下一個(gè)注冊(cè)的中間件或路由處理函數(shù)。fmt.Println(“M1 響應(yīng)部分”):這行代碼輸出 “M1 響應(yīng)部分”,表示中間件處理請(qǐng)求后的響應(yīng)部分,可以在這里執(zhí)行一些后續(xù)處理邏輯,如記錄響應(yīng)時(shí)間、清理資源等。
注釋的代碼 c.Abort()
//c.Abort():這是一個(gè)被注釋掉的代碼片段。在 Gin 框架中,如果調(diào)用 c.Abort(),它將會(huì)中止當(dāng)前請(qǐng)求鏈的執(zhí)行,不會(huì)再繼續(xù)執(zhí)行后續(xù)的中間件或路由處理函數(shù)。如果取消注釋,將會(huì)導(dǎo)致請(qǐng)求處理過(guò)程被中止,不再執(zhí)行后續(xù)的處理函數(shù)。

執(zhí)行流程:

當(dāng)有一個(gè)HTTP請(qǐng)求到達(dá)與該中間件關(guān)聯(lián)的路由時(shí),這段代碼的執(zhí)行流程如下:當(dāng)請(qǐng)求進(jìn)入時(shí),中間件輸出 “M1 請(qǐng)求部分”,執(zhí)行一些請(qǐng)求前的邏輯。
c.Next() 調(diào)用將控制權(quán)傳遞給下一個(gè)中間件或路由處理函數(shù)。如果注釋掉的 c.Abort() 被取消注釋,則請(qǐng)求的處理將在此中間件結(jié)束,不再繼續(xù)向下執(zhí)行。
如果沒(méi)有調(diào)用 c.Abort() 或者注釋掉了,請(qǐng)求將繼續(xù)執(zhí)行下一個(gè)中間件或者最終的路由處理函數(shù)。當(dāng)控制返回給該中間件時(shí)(表示后續(xù)處理完成或者中間件鏈中斷),輸出 “M1 響應(yīng)部分”,執(zhí)行一些請(qǐng)求后的邏輯。


在這里插入圖片描述

圖 36 IRoutes接口

代碼位置:RouterGroup.go的33-51行
方法解析:
Use
Use(...HandlerFunc) IRoutes
作用:注冊(cè)一個(gè)或多個(gè)中間件函數(shù),這些中間件函數(shù)會(huì)在后續(xù)的路由處理中被調(diào)用。返回值:返回 IRoutes 接口本身,以支持鏈?zhǔn)秸{(diào)用。
HTTP 方法相關(guān)路由
這些方法 (Handle, Any, GET, POST, DELETE, PATCH, PUT, OPTIONS, HEAD) 都接受路由路徑作為第一個(gè)參數(shù),后跟一個(gè)或多個(gè) HandlerFunc,表示路由處理函數(shù)。每個(gè)方法都允許注冊(cè)對(duì)應(yīng) HTTP 方法的路由處理器。
返回值:同樣返回 IRoutes 接口,支持鏈?zhǔn)秸{(diào)用,以便在代碼中可以連續(xù)調(diào)用多個(gè)路由注冊(cè)方法。
Match
Match([]string, string, ...HandlerFunc) IRoutes
參數(shù):第一個(gè)參數(shù)是 HTTP 方法的列表,第二個(gè)參數(shù)是路由路徑模式,后跟一個(gè)或多個(gè) HandlerFunc。
作用:注冊(cè)一個(gè)支持多種 HTTP 方法的路由處理器。
返回值:返回 IRoutes 接口。
靜態(tài)文件服務(wù)相關(guān)方法:
StaticFile(string, string) IRoutes:注冊(cè)單個(gè)靜態(tài)文件的路由處理器。
StaticFileFS(string, string, http.FileSystem) IRoutes:注冊(cè)單個(gè)靜態(tài)文件的路由處理器,并指定文件系統(tǒng)。
Static(string, string) IRoutes:注冊(cè)指定路徑下所有文件的靜態(tài)文件服務(wù)。
StaticFS(string, http.FileSystem) IRoutes:注冊(cè)指定路徑下所有文件的靜態(tài)文件服務(wù),并指定文件系統(tǒng)。

總結(jié):
這個(gè)接口定義了一組方法,用于在一個(gè)路由處理器中注冊(cè)路由和處理函數(shù)。通過(guò)IRoutes接口,可以方便地添加中間件、處理各種 HTTP 方法的請(qǐng)求,以及處理靜態(tài)文件服務(wù)。這種設(shè)計(jì)使得路由的注冊(cè)和處理能夠保持清晰和模塊化,符合常見(jiàn)的 Web 框架的路由管理模式。


在這里插入圖片描述

圖 37 GET方法代碼

代碼位置:routergroup.go的116-118行

函數(shù)簽名:
GET(relativePath string, handlers ...HandlerFunc):這是一個(gè)方法定義,屬于RouterGroup類型的接收者 group。它接收一個(gè)相對(duì)路徑 relativePath 和一個(gè)或多個(gè)HandlerFunc類型的處理函數(shù)作為參數(shù)。
IRoutes 是一個(gè)接口,用于表示路由集合或路由的操作。
功能說(shuō)明:
GET方法作為 RouterGroup 的一個(gè)方法,是為了注冊(cè)一個(gè)處理 GET 請(qǐng)求的路由。
relativePath string 參數(shù)表示注冊(cè)的路由的相對(duì)路徑,如 “/”、“/users” 等。
handlers ...HandlerFunc 參數(shù)是一個(gè)變長(zhǎng)參數(shù),接收一個(gè)或多個(gè) HandlerFunc 函數(shù),用來(lái)處理請(qǐng)求。
方法調(diào)用:
roup.handle(http.MethodGet, relativePath, handlers):在 GET 方法內(nèi)部,調(diào)用了 group.handle 方法,將 HTTP 方法名 “GET”、相對(duì)路徑 relativePath handlers 函數(shù)傳遞給它。
http.MethodGet 是 Go 標(biāo)準(zhǔn)庫(kù)中定義的常量,表示 HTTP GET 請(qǐng)求方法。
返回值:
return group.handle(...):GET 方法返回了group.handle(...)的結(jié)果。通常情況下,這個(gè)方法會(huì)返回路由集合或者支持路由操作的接口,以便可以進(jìn)一步鏈?zhǔn)秸{(diào)用其他路由相關(guān)的方法。
執(zhí)行流程:
在 Gin 框架中,RouterGroup 類型的 GET 方法是一個(gè)便捷方法,它內(nèi)部調(diào)用了 group.handle 方法來(lái)處理注冊(cè) GET 請(qǐng)求的路由。具體的處理流程如下:當(dāng)調(diào)用 GET 方法注冊(cè)路由時(shí),實(shí)際上是通過(guò) group.handle 方法進(jìn)行注冊(cè)。group.handle 方法會(huì)將 “GET”、relativePath handlers 作為參數(shù)傳遞給底層的路由處理器進(jìn)行處理和注冊(cè)。這樣做的好處是可以通過(guò)不同的 HTTP 方法(例如 GET, POST, PUT 等)來(lái)注冊(cè)不同的路由處理邏輯,同時(shí)保持了代碼的簡(jiǎn)潔性和可讀性。


在這里插入圖片描述

圖 38 具體處理者代碼

代碼位置:routergroup.go的86-91行

函數(shù)簽名:
handle(httpMethod, relativePath string, handlers HandlersChain):這是一個(gè)方法定義,屬于 RouterGroup 類型的接收者 group。它接收三個(gè)參數(shù):
httpMethod:表示 HTTP 請(qǐng)求方法,如 "GET"、"POST" 等。
relativePath:表示路由的相對(duì)路徑,例如 “/”、“/users” 等。
handlers HandlersChain:是一個(gè)類型為 HandlersChain 的參數(shù),表示一系列的處理函數(shù)鏈。
路徑計(jì)算和處理器組合:
calculateAbsolutePath 方法確保生成正確的完整路徑,考慮了路由組的前綴等因素。combineHandlers 方法可能用來(lái)將當(dāng)前路由組的中間件與傳入的處理函數(shù)鏈合并,確保請(qǐng)求能夠按照正確的順序執(zhí)行。
路由注冊(cè):
addRoute 方法將最終確定的HTTP方法、路徑和處理函數(shù)鏈注冊(cè)到 Gin 框架的路由引擎中,以便后續(xù)能夠根據(jù)請(qǐng)求的HTTP方法和路徑找到對(duì)應(yīng)的處理函數(shù)。
返回值:
returnObj 方法返回當(dāng)前路由組的某個(gè)接口或?qū)ο?#xff0c;用于可能的鏈?zhǔn)秸{(diào)用或其他路由相關(guān)操作。
這段代碼展示了 Gin 框架中路由注冊(cè)的核心邏輯。它負(fù)責(zé)計(jì)算路由的絕對(duì)路徑,合并處理函數(shù)鏈,最終將路由信息注冊(cè)到底層的路由引擎中。通過(guò)這種設(shè)計(jì),框架能夠支持靈活的路由定義和中間件處理,同時(shí)保證了性能和可擴(kuò)展性。


在這里插入圖片描述

圖 39 具體處理者真正構(gòu)建責(zé)任鏈代碼
代碼位置:routergroup.go的241-248行

函數(shù)簽名:
combineHandlers(handlers HandlersChain) HandlersChain:這是一個(gè)方法定義,屬于RouterGroup類型的接收者group。它接收一個(gè)類型為 HandlersChain 的參數(shù) handlers,表示一系列的處理函數(shù)鏈。返回類型為 HandlersChain,即處理函數(shù)鏈。
參數(shù)解釋:
handlers HandlersChain:表示要合并到當(dāng)前路由組 (group) 的處理函數(shù)鏈。HandlersChain 可能是一個(gè)類型為 []func(c *Context) 的切片,用于存儲(chǔ)中間件和處理函數(shù)。
計(jì)算最終大小:
finalSize := len(group.Handlers) + len(handlers):計(jì)算合并后的處理函數(shù)鏈的總長(zhǎng)度。group.Handlers 是當(dāng)前路由組已有的處理函數(shù)鏈的長(zhǎng)度,handlers 是傳入的新的處理函數(shù)鏈的長(zhǎng)度。
斷言檢查:
assert1(finalSize < int(abortIndex), "too many handlers"):使用 assert1 函數(shù)來(lái)斷言 finalSize 必須小于 abortIndex,否則會(huì)輸出 “too many handlers” 的錯(cuò)誤信息。這是為了確保合并后的處理函數(shù)鏈不會(huì)超過(guò)某個(gè)預(yù)設(shè)的最大限制,避免潛在的內(nèi)存溢出或其他問(wèn)題。
創(chuàng)建合并后的處理函數(shù)鏈:
mergedHandlers := make(HandlersChain, finalSize):根據(jù) finalSize 創(chuàng)建一個(gè)新的 HandlersChain,即 mergedHandlers,用于存儲(chǔ)合并后的處理函數(shù)鏈。
復(fù)制處理函數(shù):
copy(mergedHandlers, group.Handlers):將當(dāng)前路由組 (group) 的已有處理函數(shù)鏈復(fù)制到 mergedHandlers ``的開(kāi)頭部分。 copy(mergedHandlers[len(group.Handlers):], handlers):將傳入的新處理函數(shù)鏈 handlers 復(fù)制到 mergedHandlers 的末尾部分,從 group.Handlers 的長(zhǎng)度位置開(kāi)始復(fù)制。
返回合并后的處理函數(shù)鏈:
return mergedHandlers:返回合并后的 HandlersChain,即包含了當(dāng)前路由組的處理函數(shù)鏈和傳入的新處理函數(shù)鏈的完整鏈條。
處理函數(shù)鏈合并:
combineHandlers 方法用于將當(dāng)前路由組的已有處理函數(shù)鏈與傳入的新處理函數(shù)鏈進(jìn)行合并,確保請(qǐng)求按照正確的順序執(zhí)行所有中間件和處理函數(shù)。
長(zhǎng)度和斷言檢查:
在合并前,通過(guò)計(jì)算和斷言來(lái)確保合并后的處理函數(shù)鏈不會(huì)過(guò)長(zhǎng),以保證系統(tǒng)的穩(wěn)定性和性能。
返回值:
返回合并后的處理函數(shù)鏈,以便在路由注冊(cè)時(shí)使用。
這段代碼展示了 Gin 框架中如何處理路由組的處理函數(shù)鏈的合并邏輯。通過(guò)這種方式,框架能夠支持在路由組中動(dòng)態(tài)添加中間件和處理函數(shù),保證了靈活性和可擴(kuò)展性。


在這里插入圖片描述

圖 40 責(zé)任鏈的數(shù)據(jù)結(jié)構(gòu)
代碼位置:gin.go的54行

定義:定義了一個(gè)HandlerFunc請(qǐng)求處理者的切片,用于存儲(chǔ)HandlerFunc請(qǐng)求處理者,構(gòu)建責(zé)任鏈。


在這里插入圖片描述

圖 41 請(qǐng)求處理者的定義
代碼位置:gin.go的48行

定義:定義HandlerFunc類型,用于創(chuàng)建具體請(qǐng)求處理對(duì)象。


在這里插入圖片描述

圖 42 責(zé)任鏈訪問(wèn)下一個(gè)責(zé)任方Next()代碼
代碼位置:context.go的182-188行

方法說(shuō)明:
c.index 是 Context 結(jié)構(gòu)體中的一個(gè)字段,用于跟蹤當(dāng)前執(zhí)行的中間件或處理函數(shù)的位置。
c.handlers 是一個(gè)存儲(chǔ) HandlerFunc 的切片,這些函數(shù)是注冊(cè)到當(dāng)前路由處理器的中間件和處理函數(shù)。
c.index++ 將 index 遞增,以準(zhǔn)備執(zhí)行下一個(gè)中間件或處理函數(shù)。
for 循環(huán)用來(lái)遍歷 handlers 中的函數(shù),從 index 所指的位置開(kāi)始執(zhí)行,直到數(shù)組末尾或者中途某個(gè)函數(shù)決定中斷執(zhí)行。
執(zhí)行流程:
調(diào)用Next()方法會(huì)使 index 遞增,從而將控制權(quán)交給下一個(gè)注冊(cè)的中間件或處理函數(shù)。
每次循環(huán),通過(guò) c.handlers[c.index](c) 調(diào)用 index 所指的函數(shù),并將當(dāng)前的 Context 對(duì)象 c 傳遞給它。
循環(huán)繼續(xù),直到 index 超過(guò)了 handlers 的長(zhǎng)度或者某個(gè)中間件函數(shù)調(diào)用了 Next() 以停止后續(xù)執(zhí)行。


在這里插入圖片描述

圖43 定義攔截索引
代碼位置:context.go的50-51行

abortIndex 是一個(gè) int8 類型的常量。
math.MaxInt8int8 類型能表示的最大整數(shù),通常為 127。
>> 1 是位運(yùn)算操作,表示將 math.MaxInt8 右移一位,即將其值除以 2,得到的結(jié)果約為 63(實(shí)際值取決于具體的整數(shù)大小和運(yùn)算系統(tǒng))。
這樣設(shè)定的目的是使abortIndex成為一個(gè)比較大的數(shù)值,足以確保 c.index 大于等于 abortIndex 后可以立即停止后續(xù)的處理函數(shù)調(diào)用。

在這里插入圖片描述

圖 44 請(qǐng)求處理者設(shè)置攔截器
代碼位置:context.go的199-201行
代碼解釋:
c.index Context 結(jié)構(gòu)體中的一個(gè)字段,用于跟蹤當(dāng)前執(zhí)行的中間件或處理函數(shù)的位置。
abortIndex 是一個(gè)常量或全局變量,用于表示中止處理流程的索引值。
Abort() 方法將 c.index 設(shè)置為 abortIndex,這樣在接下來(lái)調(diào)用 Next() 方法時(shí),循環(huán)將直接結(jié)束,不再執(zhí)行后續(xù)的處理函數(shù)或中間件。


在這里插入圖片描述

圖 45 判斷請(qǐng)求處理者是否設(shè)置攔截
代碼位置:context.go的191-193行

代碼解釋:
c.index Context 結(jié)構(gòu)體中的一個(gè)字段,用于跟蹤當(dāng)前執(zhí)行的中間件或處理函數(shù)的位置。
abortIndex 是一個(gè)常量或全局變量,用于表示中止(abort)處理流程的索引值。
IsAborted() 方法通過(guò)比較 c.index 是否大于或等于abortIndex來(lái)判斷當(dāng)前處理流程是否已經(jīng)被中止。
如果c.index大于或等于 abortIndex,則返回 true,表示當(dāng)前處理已被中止;否則返回 false,表示未被中止。


責(zé)任鏈模式案例及調(diào)試分析

責(zé)任鏈模式案例編寫(xiě)如下:
下面分析一下每個(gè)部分的功能和調(diào)用流程:
結(jié)構(gòu)定義和接口:
在這里插入圖片描述

圖101 定義Handler接口
Handler 接口:
Handle(c *gin.Context) 方法用于處理請(qǐng)求。
SetNext(handler Handler) 方法用于設(shè)置下一個(gè)責(zé)任鏈節(jié)點(diǎn)。


在這里插入圖片描述

圖102 定義Middleware中間件

Middleware 結(jié)構(gòu)體:實(shí)現(xiàn)了 Handler 接口。


在這里插入圖片描述

圖103 定義中間件1的Handle方法

Handle(c *gin.Context) 方法中,打印 “M1 接收請(qǐng)求”,然后調(diào)用下一個(gè)處理者(如果存在),最后打印 “M1 得到響應(yīng)”。


在這里插入圖片描述

圖104 定義中間件2的Handle方法

Handle(c *gin.Context) 方法中,打印 “M2 接收請(qǐng)求”,然后調(diào)用下一個(gè)處理者(如果存在),最后打印 “M2 得到響應(yīng)”。


在這里插入圖片描述

圖105 定義末端中間件的Handle方法
FinalHandler 結(jié)構(gòu)體:作為最終的處理者,實(shí)現(xiàn)了 Handler 接口。
Handle(c *gin.Context) 方法中,打印 “FinalHandler 接收請(qǐng)求”,然后調(diào)用具體的業(yè)務(wù)邏輯函數(shù) Home(c),最后打印 “FinalHandler 得到響應(yīng)”。

在這里插入圖片描述

圖106 定義視圖層代碼
Home視圖層部分:

fmt.Println("Home Receiving……") 放在 Home 函數(shù)中的最開(kāi)始,這樣在請(qǐng)求到達(dá)時(shí)會(huì)立即打印 “Home Receiving……”。
c.String(200, "Home Receiving……") 在完成日志記錄后立即向客戶端發(fā)送 “Home Receiving……” 響應(yīng)
責(zé)任鏈的構(gòu)建和運(yùn)行:


在這里插入圖片描述

圖107 客戶端構(gòu)建責(zé)任鏈

解讀: 在 main 函數(shù)中:先創(chuàng)建了 Gin 引擎實(shí)例 r。再實(shí)例化了 Middleware1Middleware2FinalHandler。之后使用 SetNext 方法將它們串聯(lián)起來(lái),形成責(zé)任鏈:middleware1 -> middleware2 -> finalHandler。將middleware1.Handle方法作為 Gin 路由處理函數(shù)注冊(cè)到了根路徑 “”,這意味著當(dāng)收到 GET 請(qǐng)求時(shí),責(zé)任鏈會(huì)依次處理該請(qǐng)求。最后通過(guò) r.Run(":8080") 啟動(dòng) Gin 服務(wù)器,監(jiān)聽(tīng)在 8080 端口上。
小結(jié):責(zé)任鏈模式案例展示了如何使用 Go 和 Gin 框架構(gòu)建一個(gè)簡(jiǎn)單的責(zé)任鏈,用于處理 HTTP 請(qǐng)求。每個(gè)中間件和最終處理者都負(fù)責(zé)一部分邏輯,并通過(guò) SetNext 方法連接成鏈條,確保請(qǐng)求依次經(jīng)過(guò)每個(gè)處理者,并且每個(gè)處理者都能在適當(dāng)?shù)臅r(shí)機(jī)打印日志和處理響應(yīng)。
調(diào)試分析:
在執(zhí)行時(shí),假設(shè)收到一個(gè) GET 請(qǐng)求:
Gin 路由會(huì)將該請(qǐng)求交給 middleware1.Handle 處理。
middleware1.Handle 中會(huì)打印 “M1 接收請(qǐng)求”,然后調(diào)用 middleware2.Handle。
middleware2.Handle 中會(huì)打印 “M2 接收請(qǐng)求”,然后調(diào)用 finalHandler.Handle。
finalHandler.Handle 中會(huì)打印 “FinalHandler 接收請(qǐng)求”,然后調(diào)用 Home(c) 處理實(shí)際的業(yè)務(wù)邏輯。
Home(c) 會(huì)在控制臺(tái)打印 “Home Receiving……”,并向客戶端返回 “Home Receiving……” 字符串。
控制流會(huì)逆序返回,最終 finalHandler.Handle 打印 “FinalHandler 得到響應(yīng)”,然后依次是 middleware2.Handle 和 middleware1.Handle 的響應(yīng)打印。
Gin引擎對(duì)象啟動(dòng)成功,代碼無(wú)報(bào)錯(cuò),責(zé)任鏈構(gòu)建成功,正在監(jiān)聽(tīng)8080端口,Demo啟動(dòng)成功!具體輸出結(jié)果見(jiàn)測(cè)試結(jié)果部分。


在這里插入圖片描述

圖 108 成功啟動(dòng)責(zé)任鏈模式案例


責(zé)任鏈模式測(cè)試結(jié)果

APIfox測(cè)試工具監(jiān)聽(tīng)向8080端口發(fā)送GET請(qǐng)求:顯示Home Reciving……,說(shuō)明責(zé)任鏈構(gòu)建成功,且將信息Home Reciving……正確顯示到客戶端。
在這里插入圖片描述

圖132 Apifox發(fā)起GET測(cè)試請(qǐng)求


責(zé)任鏈模式測(cè)試結(jié)果進(jìn)一步剖析如下:
在這里插入圖片描述

圖133 責(zé)任鏈模式測(cè)試結(jié)果剖析圖


客戶端構(gòu)建責(zé)任鏈并發(fā)起監(jiān)聽(tīng)8080端口請(qǐng)求,接下來(lái)分析控制臺(tái)輸出的順序是否與調(diào)試分析的預(yù)測(cè)一致:
在這里插入圖片描述

圖134 Apifox發(fā)起GET請(qǐng)求
訪問(wèn) http://localhost:8080/ ,向服務(wù)端發(fā)出一條GET請(qǐng)求,可以看到以下控制臺(tái)輸出:

(1) 請(qǐng)求發(fā)出:
M1 接收請(qǐng)求:Middleware1 接收請(qǐng)求。與分析圖的序號(hào)①對(duì)應(yīng)
M2 接收請(qǐng)求:Middleware2 接收請(qǐng)求。與分析圖的序號(hào)②對(duì)應(yīng)
FinalHandler 接收請(qǐng)求:FinalHandler 接收請(qǐng)求。與分析圖的序號(hào)③對(duì)應(yīng)
Home視圖層 Home Receiving……:Home 函數(shù)處理請(qǐng)求,輸出 “Home Receiving……”。與分析圖的序號(hào)④對(duì)應(yīng)
同時(shí)向客戶端(APIfox發(fā)起的請(qǐng)求端)發(fā)送"Home Receiving……


(2) 接收響應(yīng):
FinalHandler 得到響應(yīng):FinalHandler 處理完請(qǐng)求,得到響應(yīng)。與分析圖的序號(hào)⑤對(duì)應(yīng)
M2 得到響應(yīng):Middleware2 得到最終處理結(jié)果的響應(yīng)。與分析圖的序號(hào)⑥對(duì)應(yīng)
M1 得到響應(yīng):Middleware1 得到 Middleware2 的響應(yīng),最終完成整個(gè)請(qǐng)求的處理。與分析圖的序號(hào)⑦對(duì)應(yīng)。
綜上,無(wú)論是控制臺(tái)輸出的結(jié)果還是客戶端顯示的信息,都與整個(gè)調(diào)試分析的結(jié)果一致,責(zé)任鏈構(gòu)建成功,測(cè)試通過(guò)!


在這里插入圖片描述

圖135服務(wù)端監(jiān)聽(tīng)端口多次測(cè)試請(qǐng)求

持續(xù)發(fā)起多次請(qǐng)求,責(zé)任鏈也能夠正常處理,不發(fā)生請(qǐng)求,則持續(xù)監(jiān)聽(tīng)端口。
再測(cè)試一下攔截請(qǐng)求的效果,這里只需要將調(diào)用下一個(gè)處理者代碼替換為c.Abort()即可,這樣就能將請(qǐng)求攔截在Middleware2處理者,而
不會(huì)傳給下一層的具體處理者。


在這里插入圖片描述

圖 136 進(jìn)行請(qǐng)求的攔截

預(yù)期結(jié)果如下:
由于在Middleware2這一層攔截掉,請(qǐng)求不會(huì)轉(zhuǎn)發(fā)給下一層處理,即最后處理者和Home業(yè)務(wù)函數(shù)的內(nèi)容都不會(huì)輸出,客戶端也不會(huì)顯示出Home Receiving…… 輸出結(jié)果預(yù)期如下:
M1 接收請(qǐng)求 M2 接收請(qǐng)求 M2 得到響應(yīng) M1 得到響應(yīng)
測(cè)試結(jié)果如下:
客戶端發(fā)起請(qǐng)求,沒(méi)有接收到Home發(fā)送的內(nèi)容,測(cè)試結(jié)果與預(yù)期一致!


在這里插入圖片描述

圖137 客戶端發(fā)起GET請(qǐng)求

再看一下控制臺(tái)輸出的內(nèi)容:只輸出M1和M2兩個(gè)中間件有關(guān)的內(nèi)容,無(wú)輸出最后處理者的內(nèi)容,測(cè)試結(jié)果與預(yù)期一致!

在這里插入圖片描述

圖138 服務(wù)端監(jiān)聽(tīng)端口輸出信息

結(jié)語(yǔ)

責(zé)任鏈模式作為一種優(yōu)秀的設(shè)計(jì)模式,在Gin框架中展現(xiàn)了其強(qiáng)大的靈活性和可擴(kuò)展性。通過(guò)本文的探討,我們深入理解了責(zé)任鏈模式在處理請(qǐng)求流程、中間件管理和異常處理方面的應(yīng)用。合理地利用責(zé)任鏈模式可以使代碼更加模塊化和可復(fù)用,從而提高了應(yīng)用程序的設(shè)計(jì)質(zhì)量和開(kāi)發(fā)效率。希望本文能夠?yàn)殚_(kāi)發(fā)者提供實(shí)用的指導(dǎo)和啟發(fā),幫助他們?cè)趯?shí)際項(xiàng)目中充分發(fā)揮責(zé)任鏈模式的優(yōu)勢(shì),構(gòu)建更加健壯和高效的Web應(yīng)用程序。


看到這里的小伙伴,恭喜你又掌握了一個(gè)技能👊
希望大家能取得勝利,堅(jiān)持就是勝利💪
我是寸鐵!我們下期再見(jiàn)💕


在這里插入圖片描述

往期好文💕

保姆級(jí)教程

【保姆級(jí)教程】Windows11下go-zero的etcd安裝與初步使用

【保姆級(jí)教程】Windows11安裝go-zero代碼生成工具goctl、protoc、go-zero

【Go-Zero】手把手帶你在goland中創(chuàng)建api文件并設(shè)置高亮


報(bào)錯(cuò)解決

【Go-Zero】Error: user.api 27:9 syntax error: expected ‘:‘ | ‘IDENT‘ | ‘INT‘, got ‘(‘ 報(bào)錯(cuò)解決方案及api路由注意事項(xiàng)

【Go-Zero】Error: only one service expected goctl一鍵轉(zhuǎn)換生成rpc服務(wù)錯(cuò)誤解決方案

【Go-Zero】【error】 failed to initialize database, got error Error 1045 (28000):報(bào)錯(cuò)解決方案

【Go-Zero】Error 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)報(bào)錯(cuò)解決方案

【Go-Zero】type mismatch for field “Auth.AccessSecret“, expect “string“, actual “number“報(bào)錯(cuò)解決方案

【Go-Zero】Error: user.api 30:2 syntax error: expected ‘)‘ | ‘KEY‘, got ‘IDENT‘報(bào)錯(cuò)解決方案

【Go-Zero】Windows啟動(dòng)rpc服務(wù)報(bào)錯(cuò)panic:context deadline exceeded解決方案


Go面試向

【Go面試向】defer與time.sleep初探

【Go面試向】defer與return的執(zhí)行順序初探

【Go面試向】Go程序的執(zhí)行順序

【Go面試向】rune和byte類型的認(rèn)識(shí)與使用

【Go面試向】實(shí)現(xiàn)map穩(wěn)定的有序遍歷的方式

http://www.risenshineclean.com/news/33781.html

相關(guān)文章:

  • 學(xué)校網(wǎng)站開(kāi)發(fā)工作室2023第二波疫情已經(jīng)到來(lái)了嗎
  • 怎么做百度推廣網(wǎng)站百度的seo關(guān)鍵詞優(yōu)化怎么弄
  • 游戲網(wǎng)站開(kāi)發(fā)計(jì)劃書(shū)搭建網(wǎng)站步驟
  • 北京網(wǎng)站建設(shè)天下公司公司網(wǎng)站建設(shè)北京
  • 京津冀協(xié)同發(fā)展規(guī)劃圖關(guān)鍵詞推廣優(yōu)化外包
  • 網(wǎng)站建設(shè)方案的企業(yè)上海seo服務(wù)外包公司
  • 大連專業(yè)做網(wǎng)站品牌推廣的作用
  • 鄭州制作網(wǎng)站哪家好黑科技引流工具
  • 建立網(wǎng)站的英文app拉新一手渠道商
  • 上海青浦做網(wǎng)站公司品牌推廣和品牌營(yíng)銷
  • 阿克頓巴網(wǎng)站建設(shè)的目的河南鄭州最新事件
  • 網(wǎng)站平臺(tái)建設(shè)咨詢合同好用的磁力搜索引擎
  • 網(wǎng)站開(kāi)發(fā)申請(qǐng)百度推廣查詢
  • 做中學(xué)網(wǎng)站現(xiàn)在做網(wǎng)絡(luò)推廣好做嗎
  • 如何自建網(wǎng)站百度識(shí)圖識(shí)別
  • 網(wǎng)站建設(shè)公司運(yùn)營(yíng)經(jīng)驗(yàn)徐州seo網(wǎng)站推廣
  • 網(wǎng)站設(shè)計(jì)需求說(shuō)明書(shū)企業(yè)網(wǎng)站大全
  • 網(wǎng)站留言系統(tǒng)編寫(xiě)代碼站長(zhǎng)工具 seo查詢
  • 物理網(wǎng)絡(luò)設(shè)計(jì)是什么寧波seo網(wǎng)絡(luò)推廣推薦
  • 網(wǎng)絡(luò)推廣銷售怎么做seo文章生成器
  • 茂名優(yōu)化網(wǎng)站建設(shè)優(yōu)化seo廠家
  • 網(wǎng)站建設(shè)應(yīng)當(dāng)注意韓國(guó)今日特大新聞
  • 網(wǎng)站建設(shè) 化工網(wǎng)絡(luò)推廣的話術(shù)怎么說(shuō)
  • 網(wǎng)站分站的實(shí)現(xiàn)方法微博推廣方式
  • 上海網(wǎng)站建設(shè)聚眾網(wǎng)絡(luò)杭州seo網(wǎng)站排名
  • 把網(wǎng)站傳到服務(wù)器上怎么做友情鏈接怎么交換
  • 有哪些網(wǎng)站可以做視頻百度一下免費(fèi)下載安裝
  • 類似百科式的網(wǎng)站建設(shè)app推廣平臺(tái)
  • asp網(wǎng)站助手北京網(wǎng)站優(yōu)化步
  • 免費(fèi)制圖網(wǎng)站關(guān)鍵詞seo公司推薦