亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

一文詳解Golang的中間件設(shè)計(jì)模式

 更新時(shí)間:2023年03月06日 14:49:49   作者:白象孫國(guó)帥  
最近在看一些rpc框架的使用原理和源碼的時(shí)候,對(duì)中間件的實(shí)現(xiàn)非常感興趣,所以這篇文章就來(lái)和大家聊聊Golang的中間件設(shè)計(jì)模式,希望對(duì)大家有所幫助

背景

記錄一下自己在go開(kāi)發(fā)和學(xué)習(xí)上的一些筆記

最近在看一些rpc框架的使用原理和源碼的時(shí)候,對(duì)中間件的實(shí)現(xiàn)非常感興趣,然后也看了一下grpc的中間件的用法,也看了別的框架的中間件的設(shè)計(jì),感覺(jué)grpc的還算是比較容易弄懂,于是記錄一下這個(gè)常用中間件的實(shí)現(xiàn)的一個(gè)原理的demo(吐槽一下其他的rpc框架分為inbound和outbound的middleware感覺(jué)好像有點(diǎn)復(fù)雜化了,所以我也不知道哪種設(shè)計(jì)會(huì)比較好,樓主是java出身,所以對(duì)反射走aop的那種模式比較熟悉,對(duì)鏈?zhǔn)秸{(diào)用的middleware有點(diǎn)不太熟悉,當(dāng)然現(xiàn)在已經(jīng)熟悉了)

Demo

所以接下來(lái)我們就來(lái)看看demo吧 首先先定義好中間件的類(lèi)型,這里我就簡(jiǎn)單定義為以下的格式

type middleware func(ctx context.Context, req interface{}, handler endpoint) (resp interface{}, err error)
  • ctx: 協(xié)程間通信帶著
  • req: 請(qǐng)求的格式,這里圖簡(jiǎn)便,直接interface{}類(lèi)型
  • resp: 同req
  • err: error

handler: endpoint類(lèi)型,真正用來(lái)發(fā)起請(qǐng)求的一個(gè)處理方法或者是經(jīng)過(guò)N層中間件包裝的后的發(fā)起請(qǐng)求的處理方法

type endpoint func(ctx context.Context, req interface{}) (resp interface{}, err error)
//ctx: 協(xié)程間通信帶著 

//req: 請(qǐng)求的格式,這里圖簡(jiǎn)便,直接interface{}類(lèi)型
//resp: 同req  
//err: error

然后既然我們要將上方的endpoint進(jìn)行包裝然后產(chǎn)生一個(gè)新的endpoint那么也就是需要一個(gè)函數(shù)去做一步的事情,input是endpoint,ouput也是endpoint

type warp func(endpoint) endpoint //就是這個(gè)warp函數(shù)

然后我們通過(guò)每次調(diào)用這個(gè)warp的定義去生成一個(gè)新的endpoint就可以產(chǎn)生一個(gè)類(lèi)似于dfs鏈?zhǔn)秸{(diào)用的一個(gè)中間件的過(guò)程,因?yàn)閷?huì)一層套一層的endpoint下去,然后當(dāng)最后一層有返回了以后就可以接著返回了,然后不斷的彈?;厝プ铋_(kāi)始的地方,因?yàn)槲覀冎虚g件的實(shí)現(xiàn)必然是要調(diào)用handler的

func(ctx context.Context, req interface{}, handler endpoint) (resp interface{}, err error) {
		fmt.Printf("before1\n")
		resp, err = handler(ctx, req)
		fmt.Printf("end1\n")
		return
}

// handler0
var handler endpoint = func(ctx context.Context, req interface{}) (resp interface{}, err error) {
	fmt.Printf("make msg\n")
	return nil, nil
} 
// middleware
var md Middleware = func(ctx context.Context, req interface{}, handler endpoint) (resp interface{}, err error) {
		fmt.Printf("before1\n")
		resp, err = handler(ctx, req)
		fmt.Printf("end1\n")
		return
}
// warp ->> handler1
handler = warp(func(e endpoint) endpoint {
		return func(ctx context.Context, req interface{}) (resp interface{}, err error) {
				return md(ctx, req, e)
			}
		})(handler)

驗(yàn)證結(jié)論

package main

import (
	"context"
	"fmt"
)

type endpoint func(ctx context.Context, req interface{}) (resp interface{}, err error)

type middleware func(ctx context.Context, req interface{}, handler endpoint) (resp interface{}, err error)

type warp func(endpoint) endpoint

func main() {
	mds := []middleware{}
	mds = append(mds, func(ctx context.Context, req interface{}, handler endpoint) (resp interface{}, err error) {
		fmt.Printf("before1\n")
		resp, err = handler(ctx, req)
		fmt.Printf("end1\n")
		return
	})
	mds = append(mds, func(ctx context.Context, req interface{}, handler endpoint) (resp interface{}, err error) {
		fmt.Printf("before2\n")
		resp, err = handler(ctx, req)
		fmt.Printf("end2\n")
		return
	})
	var handler endpoint = func(ctx context.Context, req interface{}) (resp interface{}, err error) {
		fmt.Printf("make msg\n")
		return nil, nil
	}
	for i := len(mds) - 1; i >= 0; i-- {
		handler = warp(func(e endpoint) endpoint {
			// 由于go的機(jī)制問(wèn)題如果不用tmp去存下當(dāng)前的i,那么mds[i]就會(huì)取最終的那一個(gè),就會(huì)溢出,所以在return前先保存一下i的量,然后每一個(gè)stack去存的變量就是對(duì)的
			cur := i
			return func(ctx context.Context, req interface{}) (resp interface{}, err error) {
				return mds[cur](ctx, req, e)
			}
		})(handler)
	}
	resp, err := handler(context.Background(), "ster")
	if resp != nil && err != nil {
		return
	}
}

結(jié)果是

before1
before2
make msg
end2
end1

結(jié)論:感覺(jué)有函數(shù)指針的語(yǔ)言都可以用這一套去實(shí)現(xiàn)一個(gè)中間件

以上就是一文詳解Golang的中間件設(shè)計(jì)模式的詳細(xì)內(nèi)容,更多關(guān)于Golang中間件設(shè)計(jì)模式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go語(yǔ)言入門(mén)13之runtime包案例講解

    Go語(yǔ)言入門(mén)13之runtime包案例講解

    這篇文章主要介紹了Go語(yǔ)言入門(mén)runtime包相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-05-05
  • Go 如何批量修改文件名

    Go 如何批量修改文件名

    這篇文章主要介紹了Go 批量修改文件名的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-05-05
  • go語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單http服務(wù)的方法

    go語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單http服務(wù)的方法

    這篇文章主要介紹了go語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單http服務(wù)的方法,涉及Go語(yǔ)言http操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • 利用Go語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單Ping過(guò)程的方法

    利用Go語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單Ping過(guò)程的方法

    相信利用各種語(yǔ)言實(shí)現(xiàn)Ping已經(jīng)是大家喜聞樂(lè)見(jiàn)的事情了,網(wǎng)絡(luò)上利用Golang實(shí)現(xiàn)Ping已經(jīng)有比較詳細(xì)的代碼示例,但大多是僅僅是實(shí)現(xiàn)了Request過(guò)程,而對(duì)Response的回顯內(nèi)容并沒(méi)有做接收。而Ping程序不僅僅是發(fā)送一個(gè)ICMP,更重要的是如何接收并進(jìn)行統(tǒng)計(jì)。
    2016-09-09
  • golang 如何用反射reflect操作結(jié)構(gòu)體

    golang 如何用反射reflect操作結(jié)構(gòu)體

    這篇文章主要介紹了golang 用反射reflect操作結(jié)構(gòu)體的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • GO語(yǔ)言中的方法值和方法表達(dá)式的使用方法詳解

    GO語(yǔ)言中的方法值和方法表達(dá)式的使用方法詳解

    這篇文章主要介紹了GO的方法值和方法表達(dá)式的使用方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02
  • 使用Go語(yǔ)言寫(xiě)一個(gè)Http?Server的實(shí)現(xiàn)

    使用Go語(yǔ)言寫(xiě)一個(gè)Http?Server的實(shí)現(xiàn)

    本文主要介紹了使用Go語(yǔ)言寫(xiě)一個(gè)Http?Server的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Golang 1.18新特性模糊測(cè)試用法詳解

    Golang 1.18新特性模糊測(cè)試用法詳解

    模糊測(cè)試是一種軟件測(cè)試技術(shù)。其核心思想是將自動(dòng)或半自動(dòng)生成的隨機(jī)數(shù)據(jù)輸入到一個(gè)程序中,并監(jiān)視程序異常,如崩潰,斷言失敗,以發(fā)現(xiàn)可能的程序錯(cuò)誤,比如內(nèi)存泄漏,本文給大家介紹了Golang 1.18 新特性模糊測(cè)試,感興趣的同學(xué)可以參考閱讀下
    2023-05-05
  • Golang跨平臺(tái)GUI框架Fyne的使用教程詳解

    Golang跨平臺(tái)GUI框架Fyne的使用教程詳解

    Go 官方?jīng)]有提供標(biāo)準(zhǔn)的 GUI 框架,在 Go 實(shí)現(xiàn)的幾個(gè) GUI 庫(kù)中,Fyne 算是最出色的,它有著簡(jiǎn)潔的API、支持跨平臺(tái)能力,且高度可擴(kuò)展,下面我們就來(lái)看看它的具體使用吧
    2024-03-03
  • golang特有程序結(jié)構(gòu)入門(mén)教程

    golang特有程序結(jié)構(gòu)入門(mén)教程

    GO語(yǔ)言是一門(mén)不錯(cuò)的編程語(yǔ)言能夠到達(dá)靜態(tài)編譯語(yǔ)言的安全和性能,在本文中重點(diǎn)給大家介紹goland特有程序結(jié)構(gòu)及引用類(lèi)型別名的特征,感興趣的朋友跟隨小編一起看看吧
    2021-06-06

最新評(píng)論