亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Golang > 正文

如何編寫Go語言中間件的實例教程

2020-04-01 18:57:47
字體:
來源:轉載
供稿:網友

引言

web開發的背景下,“中間件”通常意思是“包裝原始應用并添加一些額外的功能的應用的一部分”。這個概念似乎總是不被人理解,但是我認為中間件非常棒。

首先,一個好的中間件有一個責任就是可插拔并且自足。這就意味著你可以在接口級別嵌入你的中間件他就能直接運行。它不會影響你編碼方式,不是框架,僅僅是你請求處理里面的一層而已。完全沒必要重寫你的代碼,如果你想使用中間件的一個功能,你就幫他插入到那里,如果不想使用了,就可以直接移除。

縱觀Go語言,中間件是非常普遍的,即使在標準庫中。雖然開始的時候不會那么明顯,在標準庫net/http中的函數StripText或者TimeoutHandler就是我們要定義和的中間件的樣子,處理請求和相應的時候他們包裝你的handler,并處理一些額外的步驟。

一開始,我們認為編寫中間件似乎很容易,但是我們實際編寫的時候也會遇到各種各樣的坑。讓我們來看看一些例子。

1、讀取請求

在我們的示例中,所有的中間件都將接受http。處理程序作為一個參數,并返回一個http.Handler。這使得人們很容易就能把中間產品串起來。我們所有的中間產品的基本模式是這樣的:

func X(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Something here... h.ServeHTTP(w, r) })}

我們想要將所有的請求重定向到一個斜杠——比方說/message/,到它們的非斜杠等效,比如/message。我們可以這樣寫:

func TrailingSlashRedirect(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" && r.URL.Path[len(r.URL.Path)-1] == '/' { http.Redirect(w, r, r.URL.Path[:len(r.URL.Path)-1], http.StatusMovedPermanently) return } h.ServeHTTP(w, r) })}

有沒有很簡單。

2、修改請求

比方說,我們想要向請求添加一個標題,或者修改它。http.Handler文檔中指明:

除了讀取主體之外,處理程序不應該修改所提供的請求。

Go標準庫復制http.Request。請求對象在將其傳遞到響應鏈之前,我們也應該這樣做。假設我們想在每個請求上設置Request-Id頭,以便內部跟蹤。創建*Request的淺副本,并在代理之前修改標題。

func RequestID(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { r2 := new(http.Request) *r2 = *r r2.Header.Set("X-Request-Id", uuid.NewV4().String()) h.ServeHTTP(w, r2) })}

3、編寫響應頭

如果你想設置響應頭,你可以只寫它們,然后代理請求。

func Server(h http.Handler, servername string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Server", servername) h.ServeHTTP(w, r) })}

上面的問題是,如果內部處理器也設置了服務器頭,那么你的頭將被覆蓋。如果不想公開內部軟件的服務器頭,或者如果想在發送響應給客戶端之前去掉頭部,這可能會帶來問題。

要做到這一點,我們必須自己實現ResponseWriter接口。大多數時候,我們只會代理到底層的ResponseWriter,但是如果用戶試圖寫一個響應,我們就會潛入并添加我們的標題。

type serverWriter struct { w http.ResponseWriter name string wroteHeaders bool}func (s *serverWriter) Header() http.Header { return s.w.Header()}func (s *serverWriter) WriteHeader(code int) http.Header { if s.wroteHeader == false { s.w.Header().Set("Server", s.name) s.wroteHeader = true } s.w.WriteHeader(code)}func (s *serverWriter) Write(b []byte) (int, error) { if s.wroteHeader == false { // We hit this case if user never calls WriteHeader (default 200) s.w.Header().Set("Server", s.name) s.wroteHeader = true } return s.w.Write(b)}

要在我們的中間件中使用它,我們會寫:

func Server(h http.Handler, servername string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { sw := &serverWriter{ w: w, name: servername, } h.ServeHTTP(sw, r) })}

問題

如果用戶從不調用Write或WriteHeader呢?例如,有一個200狀態并且是空body,或者對選項請求的響應——我們的攔截函數都不會運行。因此,我們應該在ServeHTTP調用之后再添加校驗。

func Server(h http.Handler, servername string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { sw := &serverWriter{ w: w, name: servername, } h.ServeHTTP(sw, r) if sw.wroteHeaders == false { s.w.Header().Set("Server", s.name) s.wroteHeader = true } })}

其他ResponseWriter接口

ResponseWriter接口只需要有三種方法。但在實踐中,它也可以對其他接口作出響應,例如http.Pusher。你的中間件可能會意外地禁用HTTP/2支持,這是不好的。

// Push implements the http.Pusher interface.func (s *serverWriter) Push(target string, opts *http.PushOptions) error { if pusher, ok := s.w.(http.Pusher); ok { return pusher.Push(target, opts) } return http.ErrNotSupported}// Flush implements the http.Flusher interface.func (s *serverWriter) Flush() { f, ok := s.w.(http.Flusher) if ok { f.Flush() }}

總結

通過以上的學習,不知道大家對Go編寫中間件有沒有一個完整的認識。大家也可以嘗試著用Go去編寫一個中間件。

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩高清有码在线| 夜夜嗨av一区二区三区免费区| 成人淫片在线看| 91免费在线视频网站| 最新中文字幕亚洲| 国产精品亚洲视频在线观看| 欧美午夜片欧美片在线观看| 欧美日韩另类在线| 中文字幕日韩欧美精品在线观看| 欧美色视频日本版| 国产亚洲美女精品久久久| 亚洲网站在线看| 精品亚洲永久免费精品| 亚洲欧洲一区二区三区久久| 国产欧美精品在线播放| 亚洲成色777777女色窝| 欧美在线视频网| 97在线视频免费看| 久久五月情影视| 麻豆国产va免费精品高清在线| 欧美激情极品视频| 欧美激情视频在线免费观看 欧美视频免费一| 91精品国产综合久久久久久蜜臀| 亚洲视频欧洲视频| 色综合色综合网色综合| 亚洲自拍偷拍视频| 亚洲成人网在线| 久久国产精品久久久久久久久久| 中文字幕亚洲欧美一区二区三区| 国产精品美女久久| 欧美成人免费观看| 欧美老女人xx| 国产精品精品一区二区三区午夜版| 亚洲精品女av网站| 黑人巨大精品欧美一区二区三区| 欧美国产日韩一区二区| 国产精品视频网站| 国产视频综合在线| 96精品视频在线| 国产成人涩涩涩视频在线观看| 亚洲精品日韩激情在线电影| 欧美成人亚洲成人日韩成人| 亚洲jizzjizz日本少妇| 亚洲第一中文字幕| 国产精品久久视频| 国产精品香蕉国产| 日韩欧美精品免费在线| 色偷偷av亚洲男人的天堂| 成人网页在线免费观看| 亚洲欧美日韩一区二区三区在线| 久久全国免费视频| 国产欧美精品va在线观看| 久久久久久久久久国产| 亚洲精品视频久久| 日韩欧美精品在线观看| 热久久视久久精品18亚洲精品| 麻豆成人在线看| 成人免费淫片视频软件| 91视频免费在线| 亚洲视频在线免费观看| 中文字幕日韩av| 欧美综合一区第一页| 国产在线精品播放| 亚洲男人天堂2023| 亚洲第一精品福利| 国产在线观看不卡| 久久亚洲一区二区三区四区五区高| 欧美成人亚洲成人| 国产91九色视频| 欧美激情第一页xxx| 亚洲人成在线观看| 成人444kkkk在线观看| 国产成人精品亚洲精品| 国产精品高清在线观看| 蜜月aⅴ免费一区二区三区| 国产精品成人免费电影| 欧美成人久久久| 亚洲欧美在线免费观看| 久久久久久久999精品视频| 日韩激情在线视频| 九九九热精品免费视频观看网站| 久久久综合av| 日韩av毛片网| 欧美视频中文字幕在线| 91免费视频国产| 亚洲国产成人av在线| 日韩精品免费在线播放| 欧美影院成年免费版| 亚洲天堂一区二区三区| 国产精品久久久久久久美男| 欧美午夜无遮挡| 精品亚洲一区二区三区四区五区| 日韩一区二区三区xxxx| 欧美裸体xxxx极品少妇软件| 国产精品免费久久久久影院| 最近2019中文字幕大全第二页| 亚洲第一精品自拍| 精品国产乱码久久久久酒店| 国内外成人免费激情在线视频网站| 91探花福利精品国产自产在线| 久久不射热爱视频精品| 久久久精品电影| 国产精品视频地址| 久久久亚洲天堂| 国产精品第一视频| 久久综合久中文字幕青草| 欧美一二三视频| 色综合伊人色综合网| 欧美日韩在线视频观看| 日韩一区二区在线视频| 精品少妇一区二区30p| 97香蕉久久夜色精品国产| 久久婷婷国产麻豆91天堂| 中文字幕一区二区精品| 亚洲一区二区福利| 中文字幕亚洲国产| 国产欧美最新羞羞视频在线观看| 色七七影院综合| 亚洲视频国产视频| 91久久国产精品| 午夜精品一区二区三区在线| 久久久久久999| 日韩免费视频在线观看| 国产精品久久久久久av下载红粉| 欧美激情视频在线免费观看 欧美视频免费一| 韩国19禁主播vip福利视频| 亚洲韩国欧洲国产日产av| 国产91精品在线播放| 92看片淫黄大片看国产片| 午夜精品久久久久久久久久久久久| 国产成人精品免费久久久久| 国产最新精品视频| 国产91网红主播在线观看| 国产午夜精品视频免费不卡69堂| 中文字幕日韩在线观看| 欧美极品少妇xxxxⅹ喷水| 亚洲区一区二区| 日本亚洲精品在线观看| 亚洲成人激情在线| 亚洲欧洲激情在线| 欧美黄色片免费观看| 人体精品一二三区| 57pao国产成人免费| 亚洲一区二区三区四区视频| 亚洲国产日韩精品在线| 中文字幕日韩综合av| 亚洲国产第一页| 最近2019年中文视频免费在线观看| 3344国产精品免费看| 97视频免费看| 亚洲黄在线观看| 中文字幕日韩精品有码视频| 国产欧美精品一区二区三区-老狼| 欧美日韩激情美女| 亚洲国产成人一区| 中文字幕亚洲图片| 亚洲欧美成人精品| 九九视频直播综合网| 欧美在线观看一区二区三区| 国内精品久久久久久久久| 亚洲国产美女精品久久久久∴| 国产精品日韩在线观看| 亚洲一区美女视频在线观看免费| 亚洲成色999久久网站|