iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 18
0
DevOps

欸你這週GO了嘛系列 第 18

[DAY18]Gin-目前Golang http框架中的最速傳說

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20200924/20129515c6iewFj2AO.png
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"

http method:GET, POST, PUT, PATCH, DELETE and OPTIONS

Gin除了上面的指定method外,還有一種神奇的method叫Any,當Route的method是Any時,
會得到一種小朋友才要選擇~~我全都要的態度
https://ithelp.ithome.com.tw/upload/images/20200925/20129515azTkbz81ox.jpg
但是如果已經使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"

Path與Querystring

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"

Grouping routes

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"

上一篇
[DAY17]動手做個http服務吧~~
下一篇
[DAY19]Gin-Middleware,validator與binding
系列文
欸你這週GO了嘛30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言