這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。你好,今天我想分享一下,在 `Go` 語言中串聯 HTTP 處理器。在使用 Go 之前, 我使用 Nodejs + [ExpressJS](http://expressjs.com/en/4x/api.html) 去編寫 HTTP 伺服器應用。 這個架構提供了很簡單的方法去使用中介軟體和串聯很多路由節點,因此,不必指定完整的路由路徑來為其添加處理常式。![圖1](https://raw.githubusercontent.com/studygolang/gctt-images/master/chain-http-hanlders/1.png)這個想法是通過分割你的路由和處理每一個部分,串聯到處理器,每個處理常式只負責一部分。它理解起來非常簡單且非常容易使用和維護,所以首先我嘗試在 Go 中做一些類似的事情。開箱即用, Go 提供了一個很棒的 [http](https://golang.org/pkg/net/http) 包,它包含了很多不同的工具,當然, 還有 [`ListenAndServe`](https://golang.org/pkg/net/http/#ListenAndServe) 方法,它在給定的連接埠上啟動一個 HTTP 伺服器並且通過 [``Handler``](https://golang.org/pkg/net/http/#Handler) 處理它,那麼這個 [`Handler`](https://golang.org/pkg/net/http/#Handler) 是什嗎?```gotype Handler interface { ServeHTTP(ResponseWriter,*Request)}```[`Handler`](https://golang.org/pkg/net/http/#Handler) 是介面,它有一個方法 - ServeHTTP 去處理傳入的請求和輸出響應。但是,如果我們想為每一個根路由定義一個處理常式,例如 /api/、/home、/about 等,要怎麼做?[`ServeMux`](https://golang.org/pkg/net/http/#ServeMux) - HTTP 要求複用器,可以協助你處理這一點. 使用 [`ServeMux`](https://golang.org/pkg/net/http/#ServeMux),我們可以指定處理器方法來服務任何給定的路由,但問題是我們不能做任何嵌套的 [`ServeMux`](https://golang.org/pkg/net/http/#ServeMux)。文檔中的例子:```gomux := http.NewServeMux()mux.Handle("/api/", apiHandler{})mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {// The "/" pattern matches everything, so we need to check// that we're at the root here.if req.URL.Path != "/" {http.NotFound(w, req)return}fmt.Fprintf(w, "Welcome to the home page!")})```我們可以看到,在這個例子中為 `/api/` 路由自訂了一個處理器並且定義了一個處理方法給根路由。因此任何以 `/api/*` 開頭的路由都將使用 apiHandler 處理器方法。 但是如果我們需要串聯一個 usersHandler 到 apiHandler,不通過任何的頭腦風暴和編碼,我們無法做到這點。為此我寫了一個小庫 - [gosplitter](https://github.com/goncharovnikita/gosplitter),它只提供一個公用方法 `Match(url string, mux *http.ServeMux, http.Handler|http.HandlerFunc|interface{})` - 他匹配給定的路由部分和處理器、處理方法或你給定的任何結構!讓我們來看一個例子:```go/** * 定義一個處理器類型 */type APIV1Handler struct {mux *http.ServeMux}type ColorsHandler struct {mux *http.ServeMux}/** * Start - 綁定父級到子級 */func (a *APIV1Handler) Start() {var colorsHandler = ColorsHandler{mux: a.mux,}gosplitter.Match("/ping", a.mux, a.HandlePing())gosplitter.Match("/colors", a.mux, colorsHandler)colorsHandler.Start()}func (c *ColorsHandler) Start() { gosplitter.Match("/black", c.mux, c.HandleBlack())}/** * 簡單的HTTP處理器方法 */func (a *APIV1Handler) HandlePing() func(w http.ResponseWriter, r *http.Request) {return func(w http.ResponseWriter, r *http.Request) {w.Write([]byte("pong"))}}func (c *ColorsHandler) HandleBlack() func(w http.ResponseWriter, r *http.Request) {return func(w http.ResponseWriter, r *http.Request) {w.Write([]byte("#000000"))}}func main() { var mux = http.NewServeMux() var apiV1 = APIV1Handler{mux: mux, } /** * 綁定api處理器到根目錄 */ gosplitter.Match("/api/v1", mux, apiV1) /** * 開始api的處理 */ apiV1.Start()}```舉個例子:```go/** * 定義處理器類型 */type APIV1Handler struct {mux *http.ServeMux}type ColorsHandler struct {mux *http.ServeMux}```這裡我們定義了一個我們的處理器,它是一個結構體```go/** * Start - 綁定api處理器到根目錄 */func (a *APIV1Handler) Start() {var colorsHandler = ColorsHandler{mux: a.mux,}gosplitter.Match("/ping", a.mux, a.HandlePing())gosplitter.Match("/colors", a.mux, colorsHandler)colorsHandler.Start()}func (c *ColorsHandler) Start() {gosplitter.Match("/black", c.mux, c.HandleBlack())}```添加一個 ``Start`` 方法到我們的處理器程式,去啟用處理方法```go/** * 簡單的HTTP處理器方法 */func (a *APIV1Handler) HandlePing() func(w http.ResponseWriter, r *http.Request) {return func(w http.ResponseWriter, r *http.Request) {w.Write([]byte("pong"))}}func (c *ColorsHandler) HandleBlack() func(w http.ResponseWriter, r *http.Request) {return func(w http.ResponseWriter, r *http.Request) {w.Write([]byte("#000000"))}}```添加 `HandlePing` 和 `HandleBlack` 到我們的 `APIV1Handler`,它響應了 `pong` 和 `#000000````gofunc main() {var mux = http.NewServeMux()var apiV1 = APIV1Handler{mux: mux,}/** * 綁定API處理器到根路由 */gosplitter.Match("/api/v1", mux, apiV1)/** * 啟動API處理器 */apiV1.Start()}```我們在 `main` 方法中建立了一個新的 `ServeMux` 然後建立了一個 `APIV1Handler` 的執行個體,把它綁定到了 `/api/v1` 路由,然後啟動了它。所以在所有這些簡單的操作之後我們擁有了兩個工作中的路由: `/api/v1/ping` 和 `/api/v1/colors/black`,會響應 `pong` 和 `#000000`。使用起來不是很容易嗎?我認為是這樣, 現在在我的項目中使用這個庫來方便的進行路由分割和串聯處理器 :)<!-- Thanks for reading! Any suggestions and critiques are welcome! -->感謝閱讀,歡迎提出任何建議和批評!
via: https://medium.com/@cashalot/how-to-chain-http-handlers-in-go-33c96396b397
作者:Nikita 譯者:MarlonFan 校對:rxcai
本文由 GCTT 原創編譯,Go語言中文網 榮譽推出
本文由 GCTT 原創翻譯,Go語言中文網 首發。也想加入譯者行列,為開源做一些自己的貢獻嗎?歡迎加入 GCTT!
翻譯工作和譯文發表僅用於學習和交流目的,翻譯工作遵照 CC-BY-NC-SA 協議規定,如果我們的工作有侵犯到您的權益,請及時聯絡我們。
歡迎遵照 CC-BY-NC-SA 協議規定 轉載,敬請在本文中標註並保留原文/譯文連結和作者/譯者等資訊。
文章僅代表作者的知識和看法,如有不同觀點,請樓下排隊吐槽
503 次點擊