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

深入理解Go Gin框架中間件的實(shí)現(xiàn)原理

 更新時(shí)間:2023年09月25日 09:41:12   作者:水洗牛仔褲  
在Go Gin框架中,中間件是一種在請(qǐng)求處理過(guò)程中插入的功能模塊,它可以用于處理請(qǐng)求的前置和后置邏輯,例如認(rèn)證、日志記錄、錯(cuò)誤處理等,本文將給大家介紹一下Go Gin框架中間件的實(shí)現(xiàn)原理,需要的朋友可以參考下

中間件的實(shí)現(xiàn)原理

中間件的實(shí)現(xiàn)有:鏈?zhǔn)秸{(diào)用, 攔截器,注冊(cè)中心等方式,Gin框架使用的是 鏈?zhǔn)秸{(diào)用洋蔥模型 。

鏈?zhǔn)秸{(diào)用

鏈?zhǔn)秸{(diào)用,顧名思義就是像一個(gè)鏈子一樣連在一起,一個(gè)一個(gè)的別調(diào)用。

Gin框架中的是一個(gè)切片:

// HandlerFunc將gin中間件使用的處理程序定義為返回值。
type HandlerFunc func(*Context)
//HandlersChain定義HandlerFunc切片。
type HandlersChain []HandlerFunc

一個(gè)路由需要經(jīng)歷的所有中間件函數(shù)以及最終的處理函數(shù)都會(huì)被按照添加的順序添加到函數(shù)鏈中并儲(chǔ)存在路由樹(shù)的節(jié)點(diǎn)上。

怎么調(diào)用中間件

在Gin中實(shí)現(xiàn)了http包的Handler接口的ServerHTTP方法,(調(diào)用流程在Gin啟動(dòng)和接收請(qǐng)求的文章中介紹)。經(jīng)過(guò)ServerHTTP方法,初始化了Context結(jié)構(gòu)體,給其中index這個(gè)字段設(shè)為-1,調(diào)用c.Next時(shí)會(huì)調(diào)用到中間件函數(shù)。

ServerHTTP

// ServeHTTP實(shí)現(xiàn)http.Handler接口。
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	c := engine.pool.Get().(*Context)
	c.writermem.reset(w)
	c.Request = req
	c.reset()//初始化Context
	engine.handleHTTPRequest(c)//在這里邊調(diào)用了c.Next(),
	engine.pool.Put(c)
}

c.Next

// Next should be used only inside middleware.
// It executes the pending handlers in the chain inside the calling handler.
// See example in GitHub.
func (c *Context) Next() {
	c.index++
	for c.index < int8(len(c.handlers)) {
		c.handlers[c.index](c)//這個(gè)就是函數(shù)鏈,調(diào)用第index的函數(shù),參數(shù)為c。
		c.index++
	}
}

c.Abort

在中間件中還有一個(gè)Abort函數(shù),作用是終止執(zhí)行。

// Abort阻止調(diào)用掛起的處理程序。請(qǐng)注意,這不會(huì)停止當(dāng)前處理程序。
//假設(shè)你有一個(gè)授權(quán)中間件,它驗(yàn)證當(dāng)前請(qǐng)求是否被授權(quán)。
//如果授權(quán)失?。ɡ纾好艽a不匹配),
//則調(diào)用Abort以確保不調(diào)用此請(qǐng)求的其余處理程序。
const abortIndex int8 = math.MaxInt8 >> 1
func (c *Context) Abort() {
	c.index = abortIndex
}

洋蔥模型

就像這個(gè)洋蔥一樣,鏈?zhǔn)胶瘮?shù)是一層一層的調(diào)用的。

我們看一下Gin框架官方的兩個(gè)中間件,他們很好的體現(xiàn)了洋蔥模型。

func Default() *Engine {
	debugPrintWARNINGDefault()
	engine := New()
	engine.Use(Logger(), Recovery())
	return engine
}

Logger

func Logger() HandlerFunc {
	return LoggerWithConfig(LoggerConfig{})
}
func LoggerWithConfig(conf LoggerConfig) HandlerFunc {
	//省略初始化日志。
	return func(c *Context) {
	...
		c.Next()
		//省略將日志格式化輸出
		}
	}
}

通過(guò)前面我們知道,調(diào)用c.Next函數(shù)的時(shí)候會(huì)調(diào)用下一個(gè)函數(shù)鏈中下一個(gè)函數(shù),這時(shí)候LoggerWithConfig函數(shù)還沒(méi)有執(zhí)行完,就開(kāi)始執(zhí)行下一個(gè)函數(shù)了,當(dāng)這個(gè)c.Next執(zhí)行完成后,才會(huì)去執(zhí)行下面的語(yǔ)句了。這個(gè)過(guò)程是不是就像是一層包一層,類似于洋蔥一樣。

Recovery

func Recovery() HandlerFunc {
	return RecoveryWithWriter(DefaultErrorWriter)
}
func RecoveryWithWriter(out io.Writer, recovery ...RecoveryFunc) HandlerFunc {
	if len(recovery) > 0 {
		return CustomRecoveryWithWriter(out, recovery[0])
	}
	return CustomRecoveryWithWriter(out, defaultHandleRecovery)
}
func CustomRecoveryWithWriter(out io.Writer, handle RecoveryFunc) HandlerFunc {
	...
	return func(c *Context) {
		defer func() {
			//基本功能是去捕獲異常的
		}()
		c.Next()
	}
}

Recovery的做作用是捕獲異常的,defer后的函數(shù)的作用是去捕獲c.Next函數(shù)后的異常,防止程序崩潰。具體原理可以去看看defer,painc和recovery的運(yùn)行機(jī)制。

到此這篇關(guān)于深入理解Go Gin框架中間件的實(shí)現(xiàn)原理的文章就介紹到這了,更多相關(guān)Go Gin框架中間件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang多線程排序?qū)崿F(xiàn)快速高效地處理大規(guī)模數(shù)據(jù)

    Golang多線程排序?qū)崿F(xiàn)快速高效地處理大規(guī)模數(shù)據(jù)

    Golang多線程排序是一種快速高效地處理大規(guī)模數(shù)據(jù)的方法,通過(guò)使用Golang的協(xié)程和通道,可以將排序任務(wù)分配到多個(gè)線程中并行處理,提高了排序的效率和速度,需要詳細(xì)了解可以參考下文
    2023-05-05
  • Go中如何使用set的方法示例

    Go中如何使用set的方法示例

    這篇文章主要介紹了Go中如何使用set的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 詳解Go多協(xié)程并發(fā)環(huán)境下的錯(cuò)誤處理

    詳解Go多協(xié)程并發(fā)環(huán)境下的錯(cuò)誤處理

    這篇文章主要介紹了詳解Go多協(xié)程并發(fā)環(huán)境下的錯(cuò)誤處理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • 詳解Go 并發(fā)

    詳解Go 并發(fā)

    這篇文章主要介紹了Go 并發(fā)的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)go語(yǔ)言,感興趣的朋友可以了解下
    2020-09-09
  • Go語(yǔ)言正則表達(dá)式示例

    Go語(yǔ)言正則表達(dá)式示例

    這篇文章主要介紹了Go語(yǔ)言正則表達(dá)式,結(jié)合實(shí)例形式分析了Go語(yǔ)言正則表達(dá)式實(shí)現(xiàn)字符串的匹配、查找等相關(guān)操作技巧,需要的朋友可以參考下
    2017-01-01
  • golang包快速生成base64驗(yàn)證碼的方法

    golang包快速生成base64驗(yàn)證碼的方法

    這篇文章主要介紹了golang包快速生成base64驗(yàn)證碼的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • golang中"var"與":="的區(qū)別解析

    golang中"var"與":="的區(qū)別解析

    這篇文章主要介紹了golang中“var”與“:=”的區(qū)別,使用var關(guān)鍵字是Go最基本的定義變量方式,有時(shí)也會(huì)使用到:=來(lái)定義變量,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • Go語(yǔ)言集成開(kāi)發(fā)環(huán)境IDE詳細(xì)安裝教程

    Go語(yǔ)言集成開(kāi)發(fā)環(huán)境IDE詳細(xì)安裝教程

    VSCode是免費(fèi)開(kāi)源的現(xiàn)代化輕量級(jí)代碼編輯器,支持幾乎所有主流的開(kāi)發(fā)語(yǔ)言,內(nèi)置命令行工具和 Git 版本控制系統(tǒng),支持插件擴(kuò)展,這篇文章主要介紹了Go語(yǔ)言集成開(kāi)發(fā)環(huán)境IDE詳細(xì)安裝教程,需要的朋友可以參考下
    2021-11-11
  • Gotify搭建你的消息推送系統(tǒng)

    Gotify搭建你的消息推送系統(tǒng)

    這篇文章主要介紹了Gotify搭建你的消息推送系統(tǒng),今天要分享的是 gotify,是一個(gè)用 go 編寫的消息服務(wù)端,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2024-01-01
  • gin 獲取post請(qǐng)求的json body操作

    gin 獲取post請(qǐng)求的json body操作

    這篇文章主要介紹了gin 獲取post請(qǐng)求的json body操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-03-03

最新評(píng)論