日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
用20行代碼寫出清晰易用的Go中間件API

在使用 Go 編寫復(fù)雜的服務(wù)時(shí),您將遇到一個(gè)典型的主題是中間件。這個(gè)話題在網(wǎng)上被討論了一次又一次。本質(zhì)上,中間件允許我們做了如下事情:

創(chuàng)新互聯(lián)基于成都重慶香港及美國(guó)等地區(qū)分布式IDC機(jī)房數(shù)據(jù)中心構(gòu)建的電信大帶寬,聯(lián)通大帶寬,移動(dòng)大帶寬,多線BGP大帶寬租用,是為眾多客戶提供專業(yè)四川聯(lián)通機(jī)房服務(wù)器托管報(bào)價(jià),主機(jī)托管價(jià)格性價(jià)比高,為金融證券行業(yè)服務(wù)器托管,ai人工智能服務(wù)器托管提供bgp線路100M獨(dú)享,G口帶寬及機(jī)柜租用的專業(yè)成都idc公司。

  • 攔截 ServeHTTP 調(diào)用,執(zhí)行任意代碼
  • 對(duì)調(diào)用鏈(Continuation Chain) 上的請(qǐng)求/響應(yīng)流進(jìn)行更改
  • 打斷中間件鏈,或繼續(xù)下一個(gè)中間件攔截器并最終到達(dá)真正的請(qǐng)求處理器

這些與 express.js 中間件所做的工作非常類似。我們探索了各種庫(kù),找到了接近我們想要的現(xiàn)有解決方案,但是他們要么有不要的額外內(nèi)容,要么不符合我們的品位。顯然,我們可以在 express.js 中間件的啟發(fā)下,寫出 20 行代碼以下的更清晰的易用的 API(Installation API)

抽象

在設(shè)計(jì)抽象時(shí),我們首先設(shè)想如何編寫中間件函數(shù)(下文開始稱為攔截器),答案非常明顯:

 
 
 
  1. func NewElapsedTimeInterceptor() MiddlewareInterceptor { 
  2. return func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 
  3. startTime := time.Now() 
  4. defer func() { 
  5. endTime := time.Now() 
  6. elapsed := endTime.Sub(startTime) 
  7. // 記錄時(shí)間消耗 
  8. }() 
  9.  
  10. next(w, r) 
  11.  
  12. func NewRequestIdInterceptor() MiddlewareInterceptor { 
  13. return func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 
  14. if r.Headers.Get("X-Request-Id") == "" { 
  15. r.Headers.Set("X-Request-Id", generateRequestId()) 
  16.  
  17. next(w, r) 

它們看起來就像 http.HandlerFunc,但有一個(gè)額外的參數(shù) next,該函數(shù)(參數(shù))會(huì)繼續(xù)處理請(qǐng)求鏈。這將允許任何人像編寫類似 http.HandlerFunc 的簡(jiǎn)單函數(shù)一樣寫攔截器,它可以攔截調(diào)用,執(zhí)行所需操作,并在需要時(shí)傳遞控制權(quán)。

接下來,我們?cè)O(shè)想如何將這些攔截器連接到 http.Handler 或 http.HandlerFunc 中。為此,首先要定義 MiddlewareHandlerFunc,它只是 http.HandlerFunc 的一種類型。(type MiddlewareHandlerFunc http.HandlerFunc)。這將允許我們?cè)?http.HandlerFunc 棧上之上構(gòu)建一個(gè)更好的 API?,F(xiàn)在給定一個(gè) http.HandlerFunc 我們希望我們的鏈?zhǔn)?API 看起來像這樣:

 
 
 
  1. func HomeRouter(w http.ResponseWriter, r *http.Request) { 
  2. // 處理請(qǐng)求 
  3.  
  4. // ... 
  5. // 在程序某處注冊(cè) Hanlder 
  6. chain := MiddlewareHandlerFunc(HomeRouter). 
  7. Intercept(NewElapsedTimeInterceptor()). 
  8. Intercept(NewRequestIdInterceptor()) 
  9.  
  10. // 像普通般注冊(cè) HttpHandler 
  11. mux.Path("/home").HandlerFunc(http.HandlerFunc(chain)) 

將 http.HandlerFunc 傳遞到 MiddlewareHandlerFunc,然后調(diào)用 Intercept 方法注冊(cè)我們的 Interceptor。Interceptor 的返回類型還是 MiddlewareHandlerFunc,它允許我們?cè)俅握{(diào)用 Intercept。

使用 Intercept 組合需要注意的一件重要事情是執(zhí)行的順序。由于 chain(responseWriter, request)是間接調(diào)用最后一個(gè)攔截器,攔截器的執(zhí)行是反向的,即它從尾部的攔截器一直返回到頭部的處理程序。這很有道理,因?yàn)槟阍跀r截調(diào)用時(shí),攔截器應(yīng)該要在真正的請(qǐng)求處理器之前執(zhí)行。

簡(jiǎn)化

雖然這種反向鏈系統(tǒng)使抽象更加流暢,但事實(shí)證明,大多數(shù)情況下 s 我們有一個(gè)預(yù)編譯的攔截器數(shù)組,能夠在不同的 handlers 之間重用。同樣,當(dāng)我們將中間件鏈定義為數(shù)組時(shí),我們自然更愿意以它們執(zhí)行順序聲明它們(而不是相反的順序)。讓我們將這個(gè)數(shù)組攔截器稱為中間件鏈。我們希望我們的中間件鏈看起來有點(diǎn)像:

 
 
 
  1. // 調(diào)用鏈或中間件可以按下標(biāo)的順序執(zhí)行 
  2. middlewareChain := MiddlewareChain{ 
  3. NewRequestIdInterceptor(), 
  4. NewElapsedTimeInterceptor(), 
  5.  
  6. // 調(diào)用所有以 HomeRouter 結(jié)尾的中間件 
  7. mux.Path("/home").Handler(middlewareChain.Handler(HomeRouter)) 

實(shí)現(xiàn)

一旦我們?cè)O(shè)計(jì)好抽象的概念,實(shí)現(xiàn)就顯得簡(jiǎn)單多了

 
 
 
  1. package middleware 
  2.  
  3. import "net/http" 
  4.  
  5. // MiddlewareInterceptor intercepts an HTTP handler invocation, it is passed both response writer and request 
  6. // which after interception can be passed onto the handler function. 
  7. type MiddlewareInterceptor func(http.ResponseWriter, *http.Request, http.HandlerFunc) 
  8.  
  9. // MiddlewareHandlerFunc builds on top of http.HandlerFunc, and exposes API to intercept with MiddlewareInterceptor. 
  10. // This allows building complex long chains without complicated struct manipulation 
  11. type MiddlewareHandlerFunc http.HandlerFunc 
  12.  
  13.  
  14. // Intercept returns back a continuation that will call install middleware to intercept 
  15. // the continuation call. 
  16. func (cont MiddlewareHandlerFunc) Intercept(mw MiddlewareInterceptor) MiddlewareHandlerFunc { 
  17. return func(writer http.ResponseWriter, request *http.Request) { 
  18. mw(writer, request, http.HandlerFunc(cont)) 
  19.  
  20. // MiddlewareChain is a collection of interceptors that will be invoked in there index order 
  21. type MiddlewareChain []MiddlewareInterceptor 
  22.  
  23. // Handler allows hooking multiple middleware in single call. 
  24. func (chain MiddlewareChain) Handler(handler http.HandlerFunc) http.Handler { 
  25. curr := MiddlewareHandlerFunc(handler) 
  26. for i := len(chain) - 1; i >= 0; i-- { 
  27. mw := chain[i] 
  28. curr = curr.Intercept(mw) 
  29.  
  30. return http.HandlerFunc(curr) 

因此,在不到 20 行代碼(不包括注釋)的情況下,我們就能夠構(gòu)建一個(gè)很好的中間件庫(kù)。它幾乎是簡(jiǎn)簡(jiǎn)單單的,但是這幾行連貫的抽象實(shí)在是太棒了。它使我們能夠毫不費(fèi)力地編寫一些漂亮的中間件鏈。希望這幾行代碼也能激發(fā)您的中間件體驗(yàn)。


本文名稱:用20行代碼寫出清晰易用的Go中間件API
文章出自:http://www.5511xx.com/article/ccdhhps.html