Gin是目前Golang效能最好的http服務套件,在github上面星星數已接近42k!
Gin的特點:
當地優秀的性能表現;
擁有Go的編程思想;
基於官方net / http包的有限封裝;
使用了史上加速的路由httprouter ;
方便,靈活的中間件;
萬千寵愛於一身的gin.Context;
強大的數據綁定,解放if else代碼;
活躍的開發者
下載安裝Gin
$ go get -u github.com/gin-gonic/gin
引用Gin套件
import "github.com/gin-gonic/gin"
實作就如此簡單而粗暴
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
//defaut 8080 port
r.Run()
}
Gin預設會把每次的request都log print出來
[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 /ping --> main.main.func1 (3 handlers)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080
[GIN] 2020/09/24 - 11:47:52 | 200 | 110.566µs | 127.0.0.1 | GET "/ping"
Gin除了上面的指定method外,還有一種神奇的method叫Any,當Route的method是Any時,
會得到一種小朋友才要選擇~~我全都要的態度
但是如果已經使Any之後不能再registered相同path的hanlder,會直接panic掉
router := gin.Default()
router.Any("/DoGet", getting)
router.GET("/DoGet", getting)
//會屎掉rrr
panic: handlers are already registered for path '/DoGet'
使用Any的情形,全部method都給我來一點,但我覺得應該沒有人會需要用到這magic的method吧
[GIN-debug] GET /DoGet --> main.getting (3 handlers)
[GIN-debug] POST /DoGet --> main.getting (3 handlers)
[GIN-debug] PUT /DoGet --> main.getting (3 handlers)
[GIN-debug] PATCH /DoGet --> main.getting (3 handlers)
[GIN-debug] HEAD /DoGet --> main.getting (3 handlers)
[GIN-debug] OPTIONS /DoGet --> main.getting (3 handlers)
[GIN-debug] DELETE /DoGet --> main.getting (3 handlers)
[GIN-debug] CONNECT /DoGet --> main.getting (3 handlers)
[GIN-debug] TRACE /DoGet --> main.getting (3 handlers)
[GIN-debug] POST /DoPost --> main.main.func1 (3 handlers)
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.GET("/DoGet", getting)
router.POST("/DoPost", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "somePost"})
})
// router.Run(":8787") 指定port
router.Run()
}
func getting(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "getting"})
}
可以看的出來,Gin對method的限制跟mux回傳的http status不太一樣,mux回傳405,Gin是回傳404
[GIN] 2020/09/24 - 12:01:59 | 200 | 120.929µs | 127.0.0.1 | GET "/DoGet"
[GIN] 2020/09/24 - 12:02:02 | 404 | 612ns | 127.0.0.1 | POST "/DoGet"
[GIN] 2020/09/24 - 12:02:14 | 200 | 16.916µs | 127.0.0.1 | POST "/DoPost"
[GIN] 2020/09/24 - 12:02:19 | 404 | 580ns | 127.0.0.1 | GET "/DoPost"
Gin的優勢:
使用 : 可以定義動態路由(只能匹配到 / 以前)
使用 * 可以定義動態路由(可以匹配到 / 以後)
Gin的劣勢:沒有像mux正則match path的特性,如果真的需要帶過正則去處理的話,選擇mux是比較好的方案。
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.GET("/DoGetByPath/:param1/*param2", getting)
router.GET("/DoGetByQueryString", func(c *gin.Context) {
// Parameters key值不存在時,回傳參數2的值
p1 := c.DefaultQuery("param1", "Default")
// 也可以寫成c.Request.URL.Query().Get("param2")
//因為param2是使用*,所以可輸可不輸,但是如果使用*這前綴的話,取得的Parameters會有前綴"/"的符號存在
p2 := c.Query("param2")
c.JSON(http.StatusOK, gin.H{"param1": p1, "param2": p2})
})
// router.Run(":8787") 指定port
router.Run()
}
func getting(c *gin.Context) {
p1 := c.Param("param1")
p2 := c.Param("param2")
c.JSON(http.StatusOK, gin.H{"param1": p1, "param2": p2})
}
以下為Path Parameters使用前綴"*" 的情形
[GIN] 2020/09/24 - 13:44:12 | 200 | 86.514µs | 127.0.0.1 | GET "/DoGetByPath/gg/"
[GIN] 2020/09/24 - 13:45:06 | 200 | 26.803µs | 127.0.0.1 | GET "/DoGetByPath/gg/33"
Gin的Group跟mux的Subrouter是差不多概念的東西~~
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
g1 := router.Group("/v1")
g1.GET("/getting", getting)
g2 := router.Group("/v2")
g2.GET("/getting", getting)
// router.Run(":8787") 指定port
router.Run()
}
func getting(c *gin.Context) {
p1 := c.Param("param1")
p2 := c.Param("param2")
c.JSON(http.StatusOK, gin.H{"param1": p1, "param2": p2})
}
執行結果
[GIN] 2020/09/24 - 16:18:51 | 200 | 159.95µs | 127.0.0.1 | GET "/v1/getting"
[GIN] 2020/09/24 - 16:18:56 | 200 | 18.181µs | 127.0.0.1 | GET "/v2/getting"