還能再漲23%!AI寵兒NVIDIA成大摩明年首選AMD FSR 4.0將與RX 9070 XT顯卡同步登場羅永浩細(xì)紅線最新進(jìn)展,暫別AR,迎來AI Jarvis構(gòu)建堅實數(shù)據(jù)地基,南京打造可信數(shù)據(jù)空間引領(lǐng)數(shù)字城市建設(shè)下單前先比價不花冤枉錢 同款圖書京東價低于抖音6折日媒感慨中國電動汽車/智駕遙遙領(lǐng)先:本田、日產(chǎn)、三菱合并也沒戲消委會吹風(fēng)機(jī)品質(zhì)檢測結(jié)果揭曉 徠芬獨(dú)占鰲頭 共話新質(zhì)營銷力,2024梅花數(shù)據(jù)峰會圓滿落幕索尼影像專業(yè)服務(wù) PRO Support 升級,成為會員至少需注冊 2 臺 α 全畫幅相機(jī)、3 支 G 大師鏡頭消息稱vivo加碼電池軍備競賽:6500mAh 旗艦機(jī)+7500mAh中端機(jī)寶馬M8雙門轎跑車明年年初將停產(chǎn),后續(xù)無2026款車型比亞迪:2025 款漢家族車型城市領(lǐng)航智駕功能開啟內(nèi)測雷神預(yù)告2025年首次出席CES 將發(fā)布三款不同技術(shù)原理智能眼鏡realme真我全球首發(fā)聯(lián)發(fā)科天璣 8400 耐玩戰(zhàn)神共創(chuàng)計劃iQOO Z9 Turbo長續(xù)航版手機(jī)被曝電池加大到6400mAh,搭驍龍 8s Gen 3處理器普及放緩 銷量大跌:曝保時捷將重新評估電動汽車計劃來京東參與榮耀Magic7 RSR 保時捷設(shè)計預(yù)售 享365天只換不修國補(bǔ)期間電視迎來換機(jī)潮,最暢銷MiniLED品牌花落誰家?美團(tuán)旗下微信社群團(tuán)購業(yè)務(wù)“團(tuán)買買”宣布年底停運(yùn)消息稱微軟正與第三方廠商洽談,試圖合作推出Xbox游戲掌機(jī)設(shè)備
  • 首頁 > 網(wǎng)絡(luò)通信頻道 > 通信技術(shù)

    提升Go的HTTP路由器的提案

    2023年08月18日 16:57:27   來源:51CTO

      譯者 | 劉汪洋

      Go 的標(biāo)準(zhǔn)庫中包含一個穩(wěn)定且成熟的 HTTP 服務(wù)器。然而,內(nèi)置的請求路由器http.ServeMux 功能較為簡潔,因此你常常需要自己編寫路由代碼。

      其主要短板是,它并未支持 HTTP 方法的匹配(如GET和POST的區(qū)別),同時也無法持/users/{user}/settings這種類型的通配符路徑。然而,這兩個功能幾乎是所有 REST 風(fēng)格的 API 服務(wù)器所必需的。

      當(dāng)然,你可以選擇自行實現(xiàn)這些功能。在我以前的一篇文章 Go 中不同的 HTTP 路由方法中,提到過有一些優(yōu)秀的第三方包可以實現(xiàn)更高級的路由功能,并且只需 約 30 行代碼 就能夠在不借助任何第三方庫的情況下實現(xiàn)類似的功能。

      但是,未來可能不再需要這些替代方案和第三方包,F(xiàn)在有一個 活躍的提案 - 還包括一個旨在改進(jìn) ServeMux 參考實現(xiàn) ,使其能夠匹配 HTTP 方法和通配符路徑。

      Google 的 Go 團(tuán)隊成員 Jonathan Amsterdam 主導(dǎo)了這個提案以及之前的 討論。Jonathan 曾成功提出將結(jié)構(gòu)化日志添加到標(biāo)準(zhǔn)庫的提案 - Go 1.21 將包含他的log/slog包(預(yù)計 2023 年 8 月發(fā)布)。

      現(xiàn)狀與變革

      在目前的情況下,如果想將 GET 請求匹配到 /users/{user}/settings,你需要編寫以下的樣板代碼(盡管在實踐中你可能會使用第三方庫):

      復(fù)制

      mux.HandleFunc("/users/", func(w http.ResponseWriter, r *http.Request) {

      if r.Method != "GET" {

      http.Error(w, "method not allowed", http.StatusMethodNotAllowed)

      return

      }

      remainder := r.URL.Path[len("/users/"):]

      userId, subPath, _ := strings.Cut(remainder, "/")

      switch subPath {

      case "settings":

      fmt.Fprintf(w, "user %s", userId)

      // 其他子路徑可以在這里添加

      default:

      http.NotFound(w, r)

      }

      })

      如果接受了這個提議,你可以更加簡單地實現(xiàn)一樣的功能:

      復(fù)制

      mux.HandleFunc("GET /users/{user}/settings", func(w http.ResponseWriter, r *http.Request) {

      fmt.Fprintf(w, "user %s", r.PathValue("user"))

      })

      這樣的寫法明顯更為簡潔!

      這與其他流行路由器使用的語法非常相似:

      復(fù)制

      // github.com/go-chi/chi

      router.Get("/users/{user}/settings", func(w http.ResponseWriter, r *http.Request) {

      fmt.Fprintf(w, "user %s", chi.URLParam(r, "slug"))

      })

      // github.com/gorilla/mux

      router.HandleFunc("/users/{user}/settings", func(w http.ResponseWriter, r *http.Request) {

      fmt.Fprintf(w, "user %s", mux.Vars(r)["user"])

      }).Methods("GET")

      // github.com/bmizerany/pat

      router.Get("/users/:user/settings", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

      fmt.Fprintf(w, "user %s", r.URL.Query().Get(":user"))

      }))

      // github.com/gin-gonic/gin

      router.GET("/users/:user/settings", func(c *gin.Context) {

      fmt.Fprintf(w, "user %s", c.Param("user"))

      })

      提案中的一個有趣決定是,并沒有為 ServeMux 添加新的方法;而是對現(xiàn)有的 Handle 和 HandleFunc 方法進(jìn)行了擴(kuò)展,以支持方法前綴和 {wildcard} 路徑段。

      我理解他們避免添加新方法的想法,但我對這個決定持保留態(tài)度。遺憾的是,舊版的 ServeMux 接受如 Handle("GET /foo", h) 的模式。這意味著為增強(qiáng)版 ServeMux 編寫的代碼將在舊版 Go 上能正常編譯和運(yùn)行,但路由不會匹配到任何內(nèi)容,這容易導(dǎo)致錯誤。我可能會添加新的方法,比如 HandleMatch / HandleMatchFunc 或 Route / RouteFunc。

      該提議也詳細(xì)描述了處理兩個重疊模式的優(yōu)先級,其核心規(guī)則簡單明了:“如果兩個模式有重疊(有共同的請求),則更具體的模式優(yōu)先匹配”。

      例如,如果你注冊了模式 /users/(匹配 /users/*)以及模式 /users/{user},當(dāng)一個 /users/ben 的請求進(jìn)來時,它將匹配第二個,更具體的模式。這與現(xiàn)有的 ServeMux 中,特定主機(jī)的模式優(yōu)先于沒有主機(jī)名的模式的行為一致。

      URL 末尾通配符匹配

      此提案為我們帶來了一個新的"特殊通配符" {$},它專門用于匹配 URL 的末尾。對于那些僅希望匹配主頁路由的情況,這個新特性顯得非常實用。在此之前,要實現(xiàn)這一目標(biāo)頗為麻煩,因為以 / 結(jié)尾的模式會匹配所有 / 之下的內(nèi)容;這個規(guī)則對于只有 / 的模式同樣適用。

      因此,以前若想匹配主頁,你需要這樣操作:

      復(fù)制

      mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

      if r.URL.Path != "/" { // 確保路徑就是 "/"

      http.NotFound(w, r)

      return

      }

      serveHomepage(w, r)

      })

      mux.HandleFunc("/users", serveUsers)

      這一過程頗為繁瑣。若你忘記了路徑檢查,那么你最終可能會將主頁用于所有其他的 URL,而不是顯示一個未找到的頁面,因為所有的內(nèi)容都在 / 之下。

      而根據(jù)新的提案,這個過程將變得更加簡潔:

      復(fù)制

      mux.HandleFunc("/{$}", serveHomepage)

      mux.HandleFunc("/users", serveUsers)

      實現(xiàn)參考

      Jonathan 在 github.com/jba/muxpatterns 中發(fā)布了一個 ServeMux 的增強(qiáng)版本的示例實現(xiàn)。唯一的區(qū)別在于,由于它是在單獨(dú)的包中,無法改變 http.Request 類型, 所以你需要用 mux.PathValue(request, "name") 來獲取路徑值,而非 request.PathValue("name")。

      我在 我的 go-routing 倉庫 中添加了一個 PR,這個 PR 提供了我自己的 widget API 的一種實現(xiàn),使用 muxpatterns。這個版本與 chi 版本 非常相似 —— 清晰且易讀:

      復(fù)制

      r.HandleFunc("GET /{$}", home)

      r.HandleFunc("GET /contact", contact)

      r.HandleFunc("GET /api/widgets", apiGetWidgets)

      r.HandleFunc("POST /api/widgets", apiCreateWidget)

      r.HandleFunc("POST /api/widgets/{slug}", apiUpdateWidget)

      r.HandleFunc("POST /api/widgets/{slug}/parts", apiCreateWidgetPart)

      r.HandleFunc("POST /api/widgets/{slug}/parts/{id}/update", apiUpdateWidgetPart)

      r.HandleFunc("POST /api/widgets/{slug}/parts/{id}/delete", apiDeleteWidgetPart)

      r.HandleFunc("GET /{slug}", widgetGet)

      r.HandleFunc("GET /{slug}/admin", widgetAdmin)

      r.HandleFunc("POST /{slug}/image", widgetImage)

      當(dāng)我首次測試這個參考實現(xiàn)時,我發(fā)現(xiàn)了一些小問題,現(xiàn)已得到修復(fù)。

      結(jié)論

      盡管我對于擴(kuò)展現(xiàn)有的 Handle 和 HandleFunc 方法有一些保留,但我對這個提案的考慮感到欣慰。鑒于 Jonathan 在提案中的謹(jǐn)慎處理、他在 log/slog 上的良好表現(xiàn)以及社區(qū)的積極反饋,此提案被接受的可能性很高。

      如果這個功能能進(jìn)入標(biāo)準(zhǔn)庫,那將非常棒 —— 我開發(fā)的幾乎所有網(wǎng)站和 REST 風(fēng)格的 API 都將用到這個功能。Go 的標(biāo)準(zhǔn)庫已經(jīng)非常強(qiáng)大,但加入這個功能將進(jìn)一步減少對第三方路由器的依賴。

      如果這個功能能夠集成在 2024 年 2 月發(fā)布的 Go 1.22 中,我并不會感到驚訝。讓我們拭目以待!

      譯者介紹

      劉汪洋,51CTO社區(qū)編輯,昵稱:明明如月,一個擁有 5 年開發(fā)經(jīng)驗的某大廠高級 Java 工程師,擁有多個主流技術(shù)博客平臺博客專家稱號。

      文章內(nèi)容僅供閱讀,不構(gòu)成投資建議,請謹(jǐn)慎對待。投資者據(jù)此操作,風(fēng)險自擔(dān)。

    即時

    新聞

    明火炊具市場:三季度健康屬性貫穿全類目

    奧維云網(wǎng)(AVC)推總數(shù)據(jù)顯示,2024年1-9月明火炊具線上零售額94.2億元,同比增加3.1%,其中抖音渠道表現(xiàn)優(yōu)異,同比有14%的漲幅,傳統(tǒng)電商略有下滑,同比降低2.3%。

    企業(yè)IT

    重慶創(chuàng)新公積金應(yīng)用,“區(qū)塊鏈+政務(wù)服務(wù)”顯成效

    “以前都要去窗口辦,一套流程下來都要半個月了,現(xiàn)在方便多了!”打開“重慶公積金”微信小程序,按照提示流程提交相關(guān)材料,僅幾秒鐘,重慶市民曾某的賬戶就打進(jìn)了21600元。

    3C消費(fèi)

    華碩ProArt創(chuàng)藝27 Pro PA279CRV顯示器,高能實力,創(chuàng)

    華碩ProArt創(chuàng)藝27 Pro PA279CRV顯示器,憑借其優(yōu)秀的性能配置和精準(zhǔn)的色彩呈現(xiàn)能力,為您的創(chuàng)作工作帶來實質(zhì)性的幫助,雙十一期間低至2799元,性價比很高,簡直是創(chuàng)作者們的首選。

    研究

    中國信通院羅松:深度解讀《工業(yè)互聯(lián)網(wǎng)標(biāo)識解析體系

    9月14日,2024全球工業(yè)互聯(lián)網(wǎng)大會——工業(yè)互聯(lián)網(wǎng)標(biāo)識解析專題論壇在沈陽成功舉辦。