<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      有了net/http, 為什么還要有gin

      1. 簡介

      在Go語言中,net/http 包提供了一個強大且靈活的標準HTTP庫,可以用來構建Web應用程序和處理HTTP請求。這個包是Go語言標準庫的一部分,因此所有的Go程序都可以直接使用它。既然已經有 net/http 這樣強大和靈活的標準庫,為什么還出現了像 Gin 這樣的,方便我們構建Web應用程序的第三方庫?

      其實在于net/http的定位,其提供了基本的HTTP功能,但它的設計目標是簡單和通用性,而不是提供高級特性和便利的開發體驗。在處理HTTP請求和構建Web應用時,可能會遇到一系列的問題,這也造就了Gin 這樣的第三方庫的出現。

      下文我們將對一系列場景的介紹,通過比對 net/httpGin 二者在這些場景下的不同實現,進而說明Gin 框架存在的必要性。

      2. 復雜路由場景處理

      在實際的Web應用程序開發中,使用同一個路由前綴的場景非常普遍,這里舉兩個比較常見的例子。

      比如在設計API時,可能會隨著時間的推移對API進行更新和改進。為了保持向后兼容性,并允許多個API版本共存,通常會使用類似 /v1、/v2 這樣的路由前綴來區分不同版本的API。

      還有另外一個場景,一個大型Web應用程序經常是由多個模塊組成,每個模塊負責不同的功能。為了更好地組織代碼和區分不同模塊的路由,經常都是使用模塊名作為路由前綴。

      在這兩個場景中,大概率都會使用同一個路由前綴。如果使用net/http 來框架web應用,實現大概如下:

      package main
      
      import (
              "fmt"
              "net/http"
      )
      
      func handleUsersV1(w http.ResponseWriter, r *http.Request) {
              fmt.Fprintf(w, "User list in v1")
      }
      
      func handlePostsV1(w http.ResponseWriter, r *http.Request) {
              fmt.Fprintf(w, "Post list in v1")
      }
      
      func main() {
              http.HandleFunc("/v1/users", handleUsersV1)
              http.HandleFunc("/v1/posts", handlePostsV1)
              http.ListenAndServe(":8080", nil)
      }
      

      在上面的示例中,我們手動使用 http.HandleFunc 來定義不同的路由處理函數。

      代碼示例看起來沒有太大問題,但是是因為只有兩個路由組,如果隨著路由數量增加,處理函數的數量也會增加,代碼會變得越來越復雜和冗長。而且每一個路由規則都需要手動設置路由前綴,如例子中的 v1 前綴,如果前綴是 /v1/v2/... 這樣子設置起來,會導致代碼架構不清晰,同時操作繁雜,容易出錯。

      但是相比之下,Gin 框架實現了路由分組的功能,下面來看Gin 框架來對該功能的實現:

      package main
      
      import (
              "fmt"
              "github.com/gin-gonic/gin"
      )
      
      func main() {
              router := gin.Default()
              // 創建一個路由組
              v1 := router.Group("/v1")
              {
                      v1.GET("/users", func(c *gin.Context) {
                              c.String(200, "User list in v1")
                      })
                      v1.GET("/posts", func(c *gin.Context) {
                              c.String(200, "Post list in v1")
                      })
              }
              router.Run(":8080")
      }
      

      在上面的例子中,通過router.Group 創建了一個v1 路由前綴的路由組,我們設置路由規則時,不需要再設置路由前綴,框架會自動幫我們組裝好。

      同時,相同路由前綴的規則,也在同一個代碼塊里進行維護。 相比于 net/http 代碼庫,Gin 使得代碼結構更清晰、更易于管理。

      3. 中間件處理

      在web應用請求處理過程中,除了執行具體的業務邏輯之外,往往需要在這之前執行一些通用的邏輯,比如鑒權操作,錯誤處理或者是日志打印功能,這些邏輯我們統稱為中間件處理邏輯,而且往往是必不可少的。

      首先對于錯誤處理,在應用程序的執行過程中,可能會發生一些內部錯誤,如數據庫連接失敗、文件讀取錯誤等。合理的錯誤處理可以避免這些錯誤導致整個應用崩潰,而是通過適當的錯誤響應告知客戶端。

      對于鑒權操作,在許多web處理場景中,經常都是用戶認證之后,才能訪問某些受限資源或執行某些操作。同時鑒權操作還可以限制用戶的權限,避免用戶有未經授權的訪問,這有助于提高程序的安全性。

      因此,一個完整的HTTP請求處理邏輯,是極有可能需要這些中間件處理邏輯的。而且理論上框架或者類庫應該有對中間件邏輯的支持。下面先來看看 net/http 能怎么去實現:

      package main
      
      import (
              "fmt"
              "log"
              "net/http"
      )
      
      // 錯誤處理中間件
      func errorHandler(next http.Handler) http.Handler {
              return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                      defer func() {
                              if err := recover(); err != nil {
                                      http.Error(w, "Internal Server Error", http.StatusInternalServerError)
                                      log.Printf("Panic: %v", err)
                              }
                      }()
                      next.ServeHTTP(w, r)
              })
      }
      
      // 認證鑒權中間件
      func authMiddleware(next http.Handler) http.Handler {
              return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                      // 模擬身份驗證
                      if r.Header.Get("Authorization") != "secret" {
                              http.Error(w, "Unauthorized", http.StatusUnauthorized)
                              return
                      }
                      next.ServeHTTP(w, r)
              })
      }
      
      // 處理業務邏輯
      func helloHandler(w http.ResponseWriter, r *http.Request) {
              fmt.Fprintf(w, "Hello, World!")
      }
      
      // 另外
      func anotherHandler(w http.ResponseWriter, r *http.Request) {
              fmt.Fprintf(w, "Another endpoint")
      }
      
      func main() {
              // 創建路由處理器
              router := http.NewServeMux()
              
              // 應用中間件, 注冊處理器
              handler := errorHandler(authMiddleware(http.HandlerFunc(helloHandler)))
              router.Handle("/", handler)
              
              // 應用中間件, 注冊另外一個請求的處理器
              another := errorHandler(authMiddleware(http.HandlerFunc(anotherHandler)))
              router.Handle("/another", another)
              
              // 啟動服務器
              http.ListenAndServe(":8080", router)
      }
      

      在上述示例中,我們在net/http 中通過errorHandlerauthMiddleware 兩個中間件實現了錯誤處理和鑒權功能。 接下來我們查看示例代碼的第49行,可以發現代碼通過裝飾者模式,給原本的處理器增加了錯誤處理和鑒權操作功能。

      這段代碼的實現的優點,是通過裝飾者模式,對多個處理函數進行組合,形成處理器鏈,實現了錯誤處理和認證鑒權功能。而不需要在每個處理函數handler 中去加上這部分邏輯,這使得代碼具備更高的可讀性和可維護性。

      但是這里也存在著一個很明顯的缺點,這個功能并不是框架給我們提供的,而是我們自己實現的。我們每新增一個處理函數handler, 都需要對這個handler 進行裝飾,為其增加錯誤處理和鑒權操作,這在增加我們負擔的同時,也容易出錯。同時需求也是不斷變化的,有可能部分請求只需要錯誤處理了,一部分請求只需要鑒權操作,一部分請求既需要錯誤處理也需要鑒權操作,基于這個代碼結構,其會變得越來越難維護。

      相比之下,Gin 框架提供了一種更靈活的方式來啟用和禁用中間件邏輯,能針對某個路由組進行設置,而不需要對每個路由規則單獨設置,下面展示下示例代碼:

      package main
      
      import (
              "github.com/gin-gonic/gin"
      )
      
      func authMiddleware() gin.HandlerFunc {
              return func(c *gin.Context) {
                      // 模擬身份驗證
                      if c.GetHeader("Authorization") != "secret" {
                              c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})
                              return
                      }
                      c.Next()
              }
      }
      
      func main() {
              router := gin.Default()
              // 全局添加 Logger 和 Recovery 中間件
              // 創建一個路由組,該組中的所有路由都會應用 authMiddleware 中間件
              authenticated := router.Group("/")
              authenticated.Use(authMiddleware())
              {
                      authenticated.GET("/hello", func(c *gin.Context) {
                              c.String(200, "Hello, World!")
                      })
      
                      authenticated.GET("/private", func(c *gin.Context) {
                              c.String(200, "Private data")
                      })
              }
      
              // 不在路由組中,因此沒有應用 authMiddleware 中間件
              router.GET("/welcome", func(c *gin.Context) {
                      c.String(200, "Welcome!")
              })
      
              router.Run(":8080")
      }
      

      在上述示例中,我們通過router.Group("/") 創建了一個名為 authenticated 的路由組,然后使用 Use 方法,給該路由組啟用 authMiddleware 中間件。在這路由組下所有的路由規則,都會自動執行authMiddleware 實現的鑒權操作。

      相對于net/http 的優點,首先是不需要對每個handler 進行裝飾,增加中間件邏輯,用戶只需要專注于業務邏輯的開發即可,減輕了負擔。

      其次可維護性更高了,如果業務需要不再需要進行鑒權操作,gin 只需要刪除掉Use 方法的調用,而net/http 則需要對所有handler的裝飾操作進行處理,刪除掉裝飾者節點中的鑒權操作節點,工作量相對于gin 來說非常大,同時也容易出錯。

      最后,gin 在處理不同部分的請求需要使用不同中間件的場景下,更為靈活,實現起來也更為簡單。比如 一部分請求需要鑒權操作,一部分請求需要錯誤里處理,還有一部分既需要錯誤處理,也需要鑒權操作。這種場景下,只需要通過gin 創建三個路由組router, 然后不同的路由組分別調用 Use 方法啟用不同的中間件,即可實現需求了,這相對于net/http 更為靈活和可維護。

      這也是為什么有net/http 的前提下,還出現了gin 框架的重要原因之一。

      4. 數據綁定

      在處理HTTP請求時,比較常見的功能,是將請求中的數據自動綁定到結構體當中。下面以一個表單數據為例,如果使用net/http,如何將數據綁定到結構體當中:

      package main
      
      import (
              "fmt"
              "log"
              "net/http"
      )
      
      type User struct {
              Name  string `json:"name"`
              Email string `json:"email"`
      }
      
      func handleFormSubmit(w http.ResponseWriter, r *http.Request) {
              var user User
      
              // 將表單數據綁定到 User 結構體
              user.Name = r.FormValue("name")
              user.Email = r.FormValue("email")
      
              // 處理用戶數據
              fmt.Fprintf(w, "用戶已創建:%s (%s)", user.Name, user.Email)
      }
      
      func main() {
              http.HandleFunc("/createUser", handleFormSubmit)
              http.ListenAndServe(":8080", nil)
      }
      

      我們需要調用FormValue 方法,一個一個得從表單中讀取出數據,然后設置到結構體當中。而且在字段比較多的情況下,我們很有可能漏掉其中的某些字段,導致后續處理邏輯出現問題。而且每個字段都需要我們手動讀取設置,也很影響我們的開發效率。

      下面我們來看看Gin 是如何讀取表單數據,將其設置到結構體當中的:

      package main
      
      import (
              "fmt"
              "github.com/gin-gonic/gin"
      )
      
      type User struct {
              Name  string `json:"name"`
              Email string `json:"email"`
      }
      
      func handleFormSubmit(c *gin.Context) {
              var user User
      
              // 將表單數據綁定到 User 結構體
              err := c.ShouldBind(&user)
              if err != nil {
                      c.JSON(http.StatusBadRequest, gin.H{"error": "無效的表單數據"})
                      return
              }
      
              // 處理用戶數據
              c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("用戶已創建:%s (%s)", user.Name, user.Email)})
      }
      
      func main() {
              router := gin.Default()
              router.POST("/createUser", handleFormSubmit)
              router.Run(":8080")
      }
      

      看上面示例代碼的第17行,可以看到直接調用ShouldBind 函數,便可以自動將表單的數據自動映射到結構體當中,不再需要一個一個字段讀取,然后再單獨設置到結構體當中。

      相比于使用net/http, gin 框架在數據綁定方面更為方便,同時也不容易出錯。gin 提供了各種 api , 能夠將各種類型的數據映射到結構體當中,用戶只需要調用對應的 api 即可。而net/http 則未提供相對應的操作,需要用戶讀取數據,然后手動設置到結構體當中。

      5. 總結

      在Go語言中, net/http 提供了基本的HTTP功能,但它的設計目標是簡單和通用性,而不是提供高級特性和便利的開發體驗。在處理HTTP請求和構建Web應用時,處理復雜的路由規則時,會顯得力不從心;同時對于一些公共操作,比如日志記錄,錯誤處理等,很難做到可插拔設計;想要將請求數據綁定到結構體中,net/http 也沒有提供一些簡易的操作,都是需要用戶手動去實現的。

      這就是為什么出現了像 Gin這樣的第三方庫,其是一個構建在 net/http 之上,旨在簡化和加速Web應用程序的開發。

      總的來說,Gin 可以幫助開發者更高效地構建Web應用程序,提供了更好的開發體驗和更豐富的功能。當然,選擇使用 net/http 還是 Gin 取決于項目的規模、需求和個人喜好。對于簡單的小型項目,net/http 可能已經足夠,但對于復雜的應用程序,Gin 可能會更適合。

      posted @ 2023-08-07 08:08  菜鳥額  閱讀(337)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲理论在线A中文字幕| 精品国产自在久久现线拍| 亚洲人妻av伦理| 久久精品国产一区二区三| 国产日韩久久免费影院| 金乡县| 国产精品自拍一二三四区| 国产精品视频亚洲二区| 麻豆妓女爽爽一区二区三| 人妻性奴波多野结衣无码| 国产中文字幕在线精品| 88国产精品视频一区二区三区| 国产精品综合一区二区三区| 中文有无人妻vs无码人妻激烈| 国产不卡av一区二区| 国产精品一码在线播放| 欧美大bbbb流白水| 无码免费大香伊蕉在人线国产| 噜妇插内射精品| 久久日韩在线观看视频| 成人精品一区日本无码网| 99在线精品视频观看免费| 胸大美女又黄的网站| 九九热精彩视频在线免费| 国产免费高清69式视频在线观看| 久久精品无码一区二区小草| 日韩精品二区三区四区| 国产日韩精品一区二区在线观看播放 | 一区二区和激情视频| 亚洲成人免费一级av| 蜜桃av无码免费看永久| 91午夜福利在线观看精品| 香港日本三级亚洲三级| 精品九九人人做人人爱| 国产精品久久久久久久久久直播| 亚洲成av人片无码不卡播放器| 起碰免费公开97在线视频| 国产激情免费视频在线观看| 国产精品亚洲综合第一页| 天堂V亚洲国产V第一次| 国产WW久久久久久久久久|