成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

用 20 行代碼寫出清晰易用的 Go 中間件 API

新聞 前端
在使用 Go 編寫復雜的服務時,您將遇到一個典型的主題是中間件。這個話題在網上被討論了一次又一次。

 [[331358]]

在使用 Go 編寫復雜的服務時,您將遇到一個典型的主題是中間件。這個話題在網上被討論了一次又一次。本質上,中間件允許我們做了如下事情:

  • 攔截 ServeHTTP 調用,執行任意代碼
  • 對調用鏈(Continuation Chain) 上的請求/響應流進行更改
  • 打斷中間件鏈,或繼續下一個中間件攔截器并最終到達真正的請求處理器

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

抽象

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

  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. // 記錄時間消耗 
  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,但有一個額外的參數 next,該函數(參數)會繼續處理請求鏈。這將允許任何人像編寫類似 http.HandlerFunc 的簡單函數一樣寫攔截器,它可以攔截調用,執行所需操作,并在需要時傳遞控制權。

接下來,我們設想如何將這些攔截器連接到 http.Handler 或 http.HandlerFunc 中。為此,首先要定義 MiddlewareHandlerFunc,它只是 http.HandlerFunc 的一種類型。(type MiddlewareHandlerFunc http.HandlerFunc)。這將允許我們在 http.HandlerFunc 棧上之上構建一個更好的 API。現在給定一個 http.HandlerFunc 我們希望我們的鏈式 API 看起來像這樣:

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

將 http.HandlerFunc 傳遞到 MiddlewareHandlerFunc,然后調用 Intercept 方法注冊我們的 Interceptor。Interceptor 的返回類型還是 MiddlewareHandlerFunc,它允許我們再次調用 Intercept。

使用 Intercept 組合需要注意的一件重要事情是執行的順序。由于 chain(responseWriter, request)是間接調用最后一個攔截器,攔截器的執行是反向的,即它從尾部的攔截器一直返回到頭部的處理程序。這很有道理,因為你在攔截調用時,攔截器應該要在真正的請求處理器之前執行。

簡化

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

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

實現

一旦我們設計好抽象的概念,實現就顯得簡單多了

  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 行代碼(不包括注釋)的情況下,我們就能夠構建一個很好的中間件庫。它幾乎是簡簡單單的,但是這幾行連貫的抽象實在是太棒了。它使我們能夠毫不費力地編寫一些漂亮的中間件鏈。希望這幾行代碼也能激發您的中間件體驗。

責任編輯:張燕妮 來源: Go語言中文網
相關推薦

2013-12-12 10:55:21

2023-11-27 07:10:06

日志中間件

2015-12-21 14:56:12

Go語言Http網絡協議

2021-10-06 19:03:35

Go中間件Middleware

2022-11-18 07:54:02

Go中間件項目

2021-04-29 21:54:44

Python代碼語言

2024-05-06 12:30:51

Go語言中間件

2024-10-06 13:49:30

2016-11-11 21:00:46

中間件

2011-05-24 15:10:48

2021-02-11 08:21:02

中間件開發CRUD

2023-12-06 07:14:28

前端API中間件

2024-02-06 14:05:00

Go中間件框架

2017-12-11 13:30:49

Go語言數據庫中間件

2018-02-01 10:19:22

中間件服務器系統

2018-07-29 12:27:30

云中間件云計算API

2015-02-07 21:52:45

PaaS中間件

2013-03-13 10:37:22

中間件Windows

2018-05-02 16:23:24

中間件RPC容器

2024-08-09 08:11:02

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品久久久久久国产 | 欧美视频成人 | 日韩精品网站 | 日韩欧美专区 | 国产一区二区三区 | 一级片网站视频 | 久久综合色综合 | 久久精品免费 | 天堂综合| 综合五月 | 波多野结衣在线观看一区二区三区 | 三级黄视频在线观看 | 九九在线精品视频 | 啪啪免费 | 精品日韩在线 | 99久久99热这里只有精品 | 国产精品视频一区二区三区不卡 | 亚洲精品大片 | 精品视频在线观看 | 国产精品久久国产愉拍 | 久久夜视频 | 亚洲精选久久 | 亚洲视频免费在线播放 | 精品久久久久久国产 | 日韩中文在线视频 | 国产成人艳妇aa视频在线 | 99爱视频 | 91色网站| 久久福利电影 | 一级免费在线视频 | 久久国产精品视频 | 日韩a | 亚洲国产精品精华素 | 亚洲一区二区三区四区五区中文 | 亚洲一区二区三区免费在线观看 | 玖玖视频国产 | 日韩精品视频一区二区三区 | 成人av在线网站 | 亚洲一区 中文字幕 | 亚洲精品国产a久久久久久 中文字幕一区二区三区四区五区 | 香蕉国产在线视频 |