初級會員
  • 第 19297 位會員
  • hanzkering
  • 紅牛慕課_韓忠康
  • 540090808@qq.com
  • 2018-06-11 20:37:00
  • 272
  • Offline
  • 21 34

最近發布的主題

最近分享的資源

    暫無

最近發布的項目

    暫無

最近的評論

  • 評論了主題 Gin 文檔
    # 路由 路由系統的用于接收請求,并將請求轉發給注冊的中間件或請求處理器來處理。核心功能如下: - 路由系統可根據請求方法,請求路徑,和路徑參數來識別轉發。 - 可設置一個或多個中間件用于在請求處理器前后,處理特殊的事件。 - 可以分組設置,將一個或多個中間件作用在一組多個路由上。 ## 基本語法 我們需要先構建路由對象,也就是 `gin.Engine` 路由對象,之后在路由對象上注冊請求路徑對應的處理器(包括中間件),最后通過路由對象的 `router.Run` 方法啟動監聽。示例代碼如下: ```go r := gin.Default() r.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "pong", }) }) r.Run() // 監聽并在 0.0.0.0:8080 上啟動服務 ``` 其中: - line 1,初始化了默認的路由。 - line 2-6,針對于 GET 方式的 /ping 注冊了請求處理器,就是后邊的匿名函數。 - line 7,運行監聽。 代碼中,line 2-6 會反復的出現,我們通常需要注冊多個請求處理器完成一個完整的項目。 一個建議是將路由的定義放在獨立的文件中完成,例如在 /`router/api.go` 中完成: ```go // file /router/api.go func APIRouter() *gin.Engine { r := gin.Default() r.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "pong", }) }) // 更多的注冊 // r.POST() // r.DELETE() // r.PUT() return r } ``` 之后,在 `main.main()` 中完成調用初始化函數,并啟用監聽: ```go // file /main.go func main() { // 初始化路由 r := router.APIRouter() // 啟動服務 r.Run() } ``` ## 請求方法 ### 快捷方法 路由系統支持任意方式的請求,如下的方法用來提供對應方法來接收請求: ```go func (group *RouterGroup) DELETE(relativePath string, handlers ...HandlerFunc) IRoutes func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes func (group *RouterGroup) HEAD(relativePath string, handlers ...HandlerFunc) IRoutes func (group *RouterGroup) OPTIONS(relativePath string, handlers ...HandlerFunc) IRoutes func (group *RouterGroup) PATCH(relativePath string, handlers ...HandlerFunc) IRoutes func (group *RouterGroup) POST(relativePath string, handlers ...HandlerFunc) IRoutes func (group *RouterGroup) PUT(relativePath string, handlers ...HandlerFunc) IRoutes ``` 調用方法與上面的例子中一致。 ### 通用語法 若需要接收其他的請求方式,可以使用通用的方法 `Handle` 來注冊: ```go func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers ...HandlerFunc) IRoutes ``` 其中 httpMethod 就是請求方法字符串,例如 TRACE,CONNECT 等。 其實,類似 DELETE(),GET(),POST() 這些方法就是調用了 Handle 的快捷語法。 ### 任意方法 若需要監聽同一個請求路徑的多個任意方法,可以使用 Any(),這樣就可以同時監聽任意的請求方法了 : ```go func (group *RouterGroup) Any(relativePath string, handlers ...HandlerFunc) IRoutes ``` ## 處理器 handler 處理器,用于處理 HTTP 請求。在典型的 MVC 架構中也被叫做控制器的動作(action in controller)。是一個滿足如下前面的函數: ```go type HandlerFunc func(*Context) ``` 形式非常簡單,就是一個可以接收 `*Context` 類型(`*gin.Context`)參數的函數即可。 處理器分為兩類,中間件和請求處理器(業務邏輯處理器)。在 `router.GET()` 類的的方法中,最后一個 handler 就是請求處理器,除此之外前邊的都是中間件,必須要有一個 handler 才可以。 處理器被調用時,會接收一個 `*Context` 參數,是請求上下文,我們用于獲取請求和操作響應。請參考請求上下文,或請求,或響應章節,獲得更多內容。 ## 路由參數 指的是在路由路徑中定義的參數,例如請求 URI 是 `/user/42`,42 作為用戶的 ID,那么 42 就是路由參數。注意路由參數不是查詢字符串,例如 `/user?ID=42`, 這個 `ID=42`,也就是問號后邊的才是查詢字符串。 使用路由參數的好處是將動態 URL 變為 靜態 URL,因為請求客戶端會認為路由參數不是變化的數據,因此被視為靜態 URL。 若需要定義帶有路由參數的路徑,需要使用 `:param` 或 `*param` 的語法在路徑中。 ### 必選參數 使用 `:param` 的語法完成必選參數,例如 `/user/:ID`,即可匹配 `/user/42` 這個 URI,但不能匹配 `/user` 或 `/user/` 這個 URI,例如: ### 可選參數 使用 `*param` 的語法完成可選參數的定義,例如 `/user/*ID` 可以匹配 `/user/42` 和 `/user` 或 `/user` 的 URI,例如: ```go router.GET("/user/:ID", func(c *gin.Context) { ID := c.Param("ID") }) ``` 若沒有匹配到,則 ID 為空字符串。 ### 獲取參數 使用 gin.Context 對象的 `c.Param("param")` 來獲取參數值,參見上面的示例。 ## 路由分組 路由分組用于將多個路由進行統一的處理,例如統一的前綴,統一的中間件等。例如,在做需要認證的業務邏輯時,大量的路由需要經過認證校驗后才能交由請求處理器來完成業務邏輯,此時就可以將大量的路由定義在一個組中,集中的設置這個用于認證校驗的中間件。 ### 創建分組 使用函數 `router.Group()` 完成分組的創建。創建時可以提供路徑前綴和公用中間件,`router.Group()` 函數簽名如下: ```go func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) *RouterGroup ``` 調動該函數后,會形成一個分組路由對象,組內的路由需要使用該對象完成處理器的注冊,例如: ```go // 簡單的路由組: v1 v1 := router.Group("/v1") { v1.POST("/login", loginEndpoint) v1.POST("/submit", submitEndpoint) v1.POST("/read", readEndpoint) } // 簡單的路由組: v2 v2 := router.Group("/v2") { v2.POST("/login", loginEndpoint) v2.POST("/submit", submitEndpoint) v2.POST("/read", readEndpoint) } ``` 上面的代碼創建了兩個路由分組,前綴分別是 v1 和 v2 。本例中,并沒有設置任何的中間件,這是可行的。 注意,v1 組的路由的注冊方案,都是由 `v1.` 調用。 語法上,我們習慣(也是官方建議)將一組路由放在一個代碼塊中,在結構上保持獨立。但這個代碼塊不是必要的。 ## 中間件 中間件 middleware,也是一種處理器。主要用于在多個業務邏輯中間重用代碼,例如認證校驗,日志處理等。 中間件需要附加在路由上,使用 `router.User()` 方法。關于中間件的介紹,請參考中間件章節。 我們在使用 `gin.Default()` 初始化路由對象時,會隨之附加兩個中間件 `Logger` 和 `Recovery` ,用于完成日志和恢復的相關處理,參考的 `gin.Default()`代碼如下: ```go func Default() *Engine { debugPrintWARNINGDefault() engine := New() engine.Use(Logger(), Recovery()) return engine } ``` 其中,line 4 在注冊中間件。 若必須要使用任何中間件,可以使用函數 `gin.New()` 來創建空白的路由,例如: ```go router := gin.New() ``` 此時的路由對象,不會自動附加任何的中間件。 ## 啟動監聽 函數 `router.Run()` 用于啟動 HTTP 監聽,函數接收監聽地址作為參數,默認地址為 `:8080`。成功則守護執行,失敗則返回錯誤。 ## 常用方法索引 ### gin.New(),創建空路由 函數簽名: ```go func New() *Engine ``` 創建空白路由,不帶有任何中間件。 參數:無 返回值:*gin.Engine ### gin.Default(),創建默認路由 函數簽名: ```go func Default() *Engine ``` 創建帶有默認中間件的路由。 參數:無 返回值:*gin.Engine 默認的中間為: - Logger,日志 - Recovery,恢復 支持不同的請求方法的路由解析。通用的方法是 `router.Handle()`。 ### router.Handle(),注冊請求處理器 函數簽名: ```go func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers ...HandlerFunc) IRoutes ``` 為給定的 path 和 method 注冊處請求處理器和中間件。 最后的處理器是請求處理器,其他的處理器應是可以在不同路由間共享的中間件。 參數: - httpMethod string,請求方法 - relativePath string,相對路徑 - handlers ...HandlerFunc,處理器函數 返回值: - IRoutes,接口 除了該通用的注冊函數,常用的請求方法有快捷語法,參考下列函數: ### router.GET(),注冊 GET 方法請求處理器 函數簽名: ```go func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes ``` ### router.POST(),注冊 POST 方法請求處理器 函數簽名: ```go func (group *RouterGroup) POST(relativePath string, handlers ...HandlerFunc) IRoutes ``` ### router.PUT(),注冊 PUT 方法請求處理器 函數簽名: ```go func (group *RouterGroup) PUT(relativePath string, handlers ...HandlerFunc) IRoutes ``` ### router.DELETE(),注冊 DELETE 方法請求處理器 函數簽名: ```go func (group *RouterGroup) DELETE(relativePath string, handlers ...HandlerFunc) IRoutes ``` ### router.PATCH(),注冊 GET 方法請求處理器 函數簽名: ```go func (group *RouterGroup) PATCH(relativePath string, handlers ...HandlerFunc) IRoutes ``` ### router.HEAD(),注冊 GET 方法請求處理器 函數簽名: ```go func (group *RouterGroup) HEAD(relativePath string, handlers ...HandlerFunc) IRoutes ``` ### router.OPTIONS(),注冊 OPTIONS 方法請求處理器 函數簽名: ```go func (group *RouterGroup) OPTIONS(relativePath string, handlers ...HandlerFunc) IRoutes ``` ### router.ANY(),注冊任意方法請求處理器 函數簽名: ```go func (group *RouterGroup) ANY(relativePath string, handlers ...HandlerFunc) IRoutes ``` ### router.Run(),運行監聽 函數簽名: ```go func (engine *Engine) Run(addr ...string) (err error) ``` 啟動監聽。 參數: - addr,監聽的地址,默認為 ":8080"
  • #1 @forlittle 已更正!4例子的結果準確。多謝!
  • #1 @UYAD @UYAD 謝謝指出。別這么激動這位仁兄。`map[東:east east:東 west:西 西:west]` 這是結果。例子是在原map上增加了元素。你給的例子是增加一個新map變量存儲這個對調后的結果。本例子說明一個常規的用法,將值作為鍵,將鍵作為值而已。
  • @UYAD</a> 謝謝指出。別這么激動這位仁兄。`map[東:east east:東 west:西 西:west]` 這是結果。例子是在原map上增加了元素。你給的例子是增加一個新map變量存儲這個對調后的結果。本例子指向說明一個常規的用法,**將值作為鍵,將鍵作為值**而已。" name="content" class="comment-textarea" rows="8" style="width: 100%;"><a href="/user/UYAD" title="@UYAD">@UYAD</a> 謝謝指出。別這么激動這位仁兄。`map[東:east east:東 west:西 西:west]` 這是結果。例子是在原map上增加了元素。你給的例子是增加一個新map變量存儲這個對調后的結果。本例子想說明一個常規的用法,**將值作為鍵,將鍵作為值**而已。