在這篇文章中我們來講一講Gin
框架路由(Router
)的設定,Gin
框架的路由設定非常簡單,我們在前面幾篇學習Gin
框架的文章中,幾乎每個示例都會見到Gin
的路由定義,Gin框架就是通過定義路由以及處理該路由對應的Handler來接收使用者的Web
請求。
HttpRouter
Gin框架的路由實際是使用第三方的HttpRouter
庫,HttpRouter
是一個輕量級高效能的HTTP
請求路由器(路由多路複用器
),更簡單地理解,HttpRouter
是Go的net/http包中ServeMux更好的實現,由於Gin
框架採用了HttpRouter
,因此效能有很大的提升。
使用以下命令,可以在本地GOPATH中安裝HttpRouter
:
go get -u github.com/julienschmidt/httprouter
複製程式碼
路由與路由分組
1. 支援的HTTP方法
定義路由是為了處理HTTP請求,而HTTP請求包含不同方法,包括GET
,POST
,PUT
,PATCH
,OPTIONS
,HEAD
,DELETE
等七種方法,Gin框架中都有對應的方法來定義路由。
router := gin.New()
router.GET("/testGet",func(c *gin.Context){
//處理邏輯
})
router.POST("/testPost",func(c *gin.Context){
//處理邏輯
})
router.PUT("/testPut",func(c *gin.Context){
//處理邏輯
})
router.DELETE("/testDelete",func(c *gin.Context){
//處理邏輯
})
router.PATCH("/testPatch",func(c *gin.Context){
//處理邏輯
})
router.OPTIONS("/testOptions",func(c *gin.Context){
//處理邏輯
})
router.OPTIONS("/testHead",func(c *gin.Context){
//處理邏輯
})
複製程式碼
上面通過對應方法建立的路由,只能處理對應請求方法,如果GET定義的路由無法處理POST請求,我們可以通過Any()
方法定義可以處理任何請求的路由。
//可以處理GET,POST等各種請求
router.Any("/testAny",func(c *gin.Context){
//處理邏輯
})
複製程式碼
除了上面幾種簡便的方法,也可以使用Handle()
建立路由,通過指定Handle()
函式的第一個引數來確定處理何種請求:
//定義處理POST請求的方法
router.Handle("POST","/testHandlePost",func(c *gin.Context){
})
//定義處理GET請求的方法
router.Handle("GET","/testHandleGet",func(c *gin.Context){
})
複製程式碼
2. 路由請求路徑
定義路由時,都需要定義該路由的請求路徑,在Gin框架中,通過其支援的多種請求方法,可以很容易實現Restful風格Api請求路徑。
在前面的示例中,都是使用直接匹配的路由路徑,如下面的程式碼,只能匹配請求路徑為test
的請求。
router.GET("test",func(c *gin.Context){
})
複製程式碼
除了直接匹配路徑,Gin框架還支援使用萬用字元冒號(:)和星號(*)來匹配請求路徑,如:
使用冒號(:)定義路由路徑:
router.GET("user/:name",func(c *gin.Context){
})
複製程式碼
上面的請求路徑,請求結果對應如下:
/user/gordon 匹配
/user/you 匹配
/user/gordon/profile 不匹配
/user/ 不匹配
複製程式碼
使用星號(*)定義路由請求路徑:
router.GET("user/*name",func(c *gin.Context){
})
複製程式碼
上面的請求路徑,請求結果對應如下:
/user/gordon 匹配
/user/you 匹配
/user/gordon/profile 匹配
/user/ 匹配
複製程式碼
3. 路由分組
在前面的示例中,當我們通過gin.New()
或gin.Default()
方法建立gin.Engine
結構體例項時,然後可以使用該例項中的GET
,POST
,PUT
,PATCH
,OPTIONS
,HEAD
,DELETE
等方法來定義處理請求的路由,而其實gin.Engine
的路由功能是通過組合gin.RouterGroup
來實現的,從下面的gin.Engine
程式碼可以看出。
通過組合的方式,獲取其他資料型別的欄位和方法,正是Go語言物件導向編碼的體現。
gin.Engine
的定義:
type Engine struct {
RouterGroup //組合gin.RouterGroup
//省略其他欄位
}
複製程式碼
而直接通過gin.New()
或gin.Default()
方法建立的gin.Engine
物件來建立路由時,實際這些路由看起來並沒有在某個路由分組下,而實際上這些路由可以根路由分組
下面。
可以理解為,在Gin中定義的所有路由,都在根路由分組下面
gin.RouterGroup
的定義:
type RouterGroup struct {
Handlers HandlersChain
// contains filtered or unexported fields
}
複製程式碼
定義路由分組
使用gin.RouterGroup
的Group()
方法可以定義路由分組,如下所示:
注意,下面使用花括號
{}
將分組下的路由包起來,只是為了更加直觀,並非必要的。
router := gin.New()
user := router.Group("user")
{
user.GET("profile",func(c *gin.Context)(){
//處理邏輯
})
user.POST("modify-password",func(c *gin.Context)(){
//處理邏輯
})
}
複製程式碼
在路由中使用中介軟體
我們在《Go Web輕量級框架Gin學習系列:中介軟體使用詳解》這篇文章中已經講過在路由中如何使用中介軟體,下面作一個更加全面的瞭解。
1. Use()方法:全域性中介軟體
Use()方法定義如下:
func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes
複製程式碼
示例程式碼
router := gin.New()
router.Use(gin.Loggter())//全域性中介軟體
複製程式碼
為什麼通過gin.Engine
返回的結構體中的Use()呼叫中介軟體是全域性中介軟體呢?原因在於所有的路由分組都在根路由分組
下面。
2. 在分組中使用中介軟體
router := gin.New()
user := router.Group("user",gin.Logger())//通過Group第二個引數,使用中介軟體
{
user.GET("profile",func(c *gin.Context)(){
//處理邏輯
})
user.POST("modify-password",func(c *gin.Context)(){
//處理邏輯
})
}
複製程式碼
也可以使用返回的RouterGroup中的Use方法為路由分組應用中介軟體:
user := router.Group("user",gin.Logger()).Use(gin.Recovery())
複製程式碼
3. 在單個路由使用中介軟體
下面程式碼演示了在單個路由定義使用中介軟體的用法:
router := gin.New()
router.GET("profile",gin.Logger(),gin.Recovery(),func(c *gin.Context)(){
//處理邏輯
})
複製程式碼
或者在GET等方法之後,再使用Use()方法,為該路由應用中介軟體:
router.GET("profile",func(c *gin.Context)(){
//處理邏輯
}).Use(gin.Logger(),gin.Recovery())
複製程式碼
小結
第三方庫HttpRouter
定義了自己內建路由多路複用器(mux
),彌補了Go語言net/http
包中內建路由多路複用器的不足,而Gin框架中路由是在HttpRouter
庫之上的封裝,更加易於使用,我們可以定義單個路由接收使用者請求,也可以將路由分組,更加易於管理,也易於應用中介軟體,進行統一攔截處理。