Gin 框架 -三-: 路由初使用
1. 介紹
Gin
框架的路由功能是基於 httprouter(https://github.com/julienschmidt/httprouter) 設計的,httprouter
是一由golang
實現的路由組件。httprouter
使用基數樹 (也叫基數特里樹或壓縮前綴樹) 這種數據結構來維護映射路由關係,通過前綴樹快速路由。同時其裏面的HttpRouter
結構體實現了golang
的net.http.server
的Handler
接口,可以作爲httpHandle
發佈。
基數樹(
Radix Tree
)又稱爲PAT
位樹(Patricia Trie or crit bit tree
),是一種更節省空間的前綴樹(Trie Tree
)。對於基數樹的每個節點,如果該節點是唯一的子樹的話,就和父節點合併。
image-20210425225051144
2.HTTP 方法
在Gin
框架中對HTTP
常見相關方法 (GET、POST、PUT、DELETE、HEAD等
) 已經做了封裝,直接調用就會快速註冊相關路由,源碼所在文件位置:github.com/gin-gonic/gin/routergroup.go
2.1 使用示例
main.go 源碼 (https://github.com/52lu/gin-use/blob/main/main.go)
routing_use.go 源碼 (https://github.com/52lu/gin-use/blob/main/practise/routing_use.go)
--------------------------- main.go 代碼 -------------------------------
package main
import (
"github.com/gin-gonic/gin" // 引入Gin框架
"go-use/practise" //引入使用示例代碼包
)
func main() {
// 創建一個默認的路由引擎
engine := gin.Default()
// 調用HTTP方法路由
practise.UseHttp(engine)
_ = engine.Run()
}
----------------------- go-use/practise/routing_use.go代碼 -----------------------
// 學習使用HTTP方法
func UseHttp(engine *gin.Engine) {
// 使用Get方法
engine.GET("/get", func(context *gin.Context) {
context.JSON(200,gin.H{"msg":"請求成功","method":"get"})
})
// 使用Post方法
engine.POST("/post", func(context *gin.Context) {
context.JSON(200,gin.H{"msg":"請求成功","method":"post"})
})
// 使用PUT方法
engine.PUT("/put", func(context *gin.Context) {
context.JSON(200,gin.H{"msg":"請求成功","method":"put"})
})
// 使用DELETE方法
engine.DELETE("/del", func(context *gin.Context) {
context.JSON(200,gin.H{"msg":"請求成功","method":"del"})
})
// 使用HEAD方法
engine.HEAD("/head", func(context *gin.Context) {
context.JSON(200,gin.H{"msg":"請求成功","method":"head"})
})
}
啓動日誌輸出:
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /get --> go-use/practise.UseHttp.func1 (3 handlers)
[GIN-debug] POST /post --> go-use/practise.UseHttp.func2 (3 handlers)
[GIN-debug] PUT /put --> go-use/practise.UseHttp.func3 (3 handlers)
[GIN-debug] DELETE /del --> go-use/practise.UseHttp.func4 (3 handlers)
[GIN-debug] HEAD /head --> go-use/practise.UseHttp.func5 (3 handlers)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080
調用示例:
# GET請求
➜ ~ curl -X GET http://127.0.0.1:8080/get
{"method":"get","msg":"請求成功"}%
# 使用GET請求接收post的路由會報錯
➜ ~ curl -X GET http://127.0.0.1:8080/post
404 page not found%
# POST請求
➜ ~ curl -X POST http://127.0.0.1:8080/post
{"method":"post","msg":"請求成功"}%
# PUT 請求
➜ ~ curl -X PUT http://127.0.0.1:8080/put
{"method":"put","msg":"請求成功"}%
# DELETE請求
➜ ~ curl -X DELETE http://127.0.0.1:8080/del
{"method":"del","msg":"請求成功"}%
# HEAD請求
➜ ~ curl -i -X HEAD http://127.0.0.1:8080/head
Warning: Setting custom HTTP method to HEAD with -X/--request may not work the
Warning: way you want. Consider using -I/--head instead.
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Mon, 26 Apr 2021 08:55:19 GMT
Content-Length: 38
需要注意的是: 當路由註冊成指定 HTTP 方法時, 必須以同樣的方式請求,否則會返回:
404 page not found
2.2 匹配所有 HTTP 請求
使用Any
方法,可以匹配所有的HTTP
的方法 (GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE
)
使用示例如下:
func main() {
// 創建一個默認的路由引擎
engine := gin.Default()
// 匹配HTTP方法方法
engine.Any("/all", func(context *gin.Context) {
context.JSON(200,gin.H{"msg":"success"})
})
_ = engine.Run()
}
3. 註冊規則
3.1 定義
根據上面示例,可以總結註冊HTTP
方法路由時,規則如下:
// engine := gin.Default()
engine.MethodName(path string, ...HandlerFunc)
-
path
: 代表的是路徑 -
...HandlerFunc
: 一個或多個接收請求的處理函數。
3.2 傳多個HandlerFunc
示例
package main
import (
"github.com/gin-gonic/gin" // 引入Gin框架
)
func main() {
// 創建一個默認的路由引擎
engine := gin.Default()
// 註冊路由,接收兩個HandlerFunc
engine.GET("/handler",handFuncA,handFuncB)
_ = engine.Run()
}
func handFuncA(ctx *gin.Context) {
ctx.JSON(200, gin.H{"msg": "handFuncA"})
}
func handFuncB(ctx *gin.Context) {
ctx.JSON(200, gin.H{"msg": "handFuncB"})
}
請求輸出:
➜ curl -X GET http://127.0.0.1:8080/handler
{"msg":"handFuncA"}{"msg":"handFuncB"}
4. 匹配規則
由於Gin
路由採用的是httprouter
, 而httprouter
的路徑匹配規則整理如下
4.1 /path
這類路徑只會匹配/path
,@@注意: 不會匹配/path/
。
a. 啓動服務
func main() {
// 創建一個默認的路由引擎
engine := gin.Default()
// 註冊路由
engine.GET("/test", func(context *gin.Context) {
context.JSON(200, gin.H{
"msg": "success",
})
return
})
_ = engine.Run()
}
b. 發起請求
# 會匹配
➜ curl -X GET http://127.0.0.1:8080/test
{"msg":"success"}
# 命令行請求返回,用瀏覽器請求會正常返回
➜ ~ curl -X GET http://127.0.0.1:8080/test/
<a href="/test">Moved Permanently</a>
@注意: 當註冊路由路徑是:/path
時, 不會匹配/path/
, 用命令請求則返回<a href="/test">Moved Permanently</a>
, 但是用瀏覽器請求則會正常返回。原因: httprouter
默認開啓自動重定向,/path/
會被重定向到/path
, 如下圖所示:
image-20210426202030006
4.2 :param
:param
: 都是參數的名稱
a. 匹配規則
b. 啓動服務
package main
import (
"github.com/gin-gonic/gin" // 引入Gin框架
)
func main() {
// 創建一個默認的路由引擎
engine := gin.Default()
// 註冊路由
engine.GET("/test/:name", func(context *gin.Context) {
// 接收參數
name := context.Param("name")
context.JSON(200, gin.H{"msg": "success", "name": name})
})
engine.GET("/test/:name/:age", func(context *gin.Context) {
// 接收參數
name := context.Param("name")
age := context.Param("age")
context.JSON(200, gin.H{
"msg": "success",
"name": name,
"phone":age,
})
})
engine.GET("/test/:name/:age/:height", func(context *gin.Context) {
// 接收參數
name := context.Param("name")
age := context.Param("age")
height := context.Param("height")
context.JSON(200, gin.H{
"msg": "success",
"name": name,
"phone":age,
"height":height,
})
})
_ = engine.Run()
}
c. 發起請求
➜ curl -X GET http://127.0.0.1:8080/test/張三
{"msg":"success","name":"張三"}
➜ curl -X GET http://127.0.0.1:8080/test/張三/18
{"msg":"success","name":"張三","phone":"18"}
➜ curl -X GET http://127.0.0.1:8080/test/張三/18/170
{"height":"170","msg":"success","name":"張三","phone":"18"}
4.3 *param
從指定位置開始 (包含前綴
"/"
) 匹配到結尾。
a. 匹配規則
b. 啓動服務
package main
import (
"github.com/gin-gonic/gin" // 引入Gin框架
)
func main() {
// 創建一個默認的路由引擎
engine := gin.Default()
// 註冊路由
engine.GET("/test/*param", func(context *gin.Context) {
// 接收參數
param := context.Param("param")
context.JSON(200, gin.H{"msg": "success", "name": param})
})
_ = engine.Run()
}
c. 發起請求
➜ curl -X GET http://127.0.0.1:8080/test/張三
{"msg":"success","name":"/張三"}
➜ curl -X GET http://127.0.0.1:8080/test/張三/1
{"msg":"success","name":"/張三/1"}
➜ curl -X GET http://127.0.0.1:8080/test/張三/1/2
{"msg":"success","name":"/張三/1/2"}
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/p7e6LxU3GKsfSK-LJ1cfdg