大多數人選擇Gin無非是被效能所吸引,它們在自己的Github簡介上大大方方這樣介紹自己:
Gin is a web framework written in Go (Golang). It features a martini-like API with much better performance, up to 40 times faster thanks to httprouter. If you need performance and good productivity, you will love Gin.
這邊有兩個關鍵字可以稍微提一下:martini是一種酒的名稱,中文翻譯為「馬丁尼」,同時也是一種Go的Web framework,曾經相當受到工程師喜愛,可惜已經宣布不再繼續維護了。這點也間接讓gin的人氣更旺,不少人因此跳槽到gin的陣營。
Go原生的router設計常常被人所詬病,許多框架也都是以此為出發點設計,httprouter更是其中的佼佼者。不僅開發上更有效率也更友善,更重要的是速度快上40倍,我想很少工程師能抵擋這樣的誘惑。
坦白說我也知道一個框架只花一天一定是不夠的,所以除了Hello World以外,大概就稍微帶到一點特性。幸運的是有關Gin的教學非常多,所以剩下的就要靠有興趣的朋友自行探索了。
要安裝gin與其他go的函數包一樣,使用go get
指令,要確認GOPATH
已經設置完成(前面幾天有講過):
go get -u github.com/gin-gonic/gin
可能會花一些時間,看網路的品質而定。
在程式上方引入gin:
import "github.com/gin-gonic/gin"
如果單純要使用gin的功能,這樣就可以了。但官方有建議如果會用到http.StatusOK
之類的常數,你接著引入:
import "net/http"
這邊只是代表個意境,實際上我們參考官方範例,使用的是ping pong的例子,代表一去一回,參考範例如下:
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",
})
})
r.Run(":3000")
}
有沒有覺得很簡潔呢!這邊特別說明一下r.Run()
如果不加參數,預設是跑8080
port,但我比較喜歡3000
port所以範例修改了一下(Ruby的習慣)。把server跑起來之後,終於看到專業的伺服器console log,告別過去純go server什麼都沒有一片空白的孤寂感:
[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] Listening and serving HTTP on :3000
[GIN] 2018/11/02 - 22:32:04 | 200 | 140.255µs | ::1 | GET /ping
我想我是被框架寵壞了,一點一點元件都要自己拼湊還真不習慣,果然還是官方配置好的東西適合我的口味XD看到這樣專業的回饋真是讓我自信心大增。
這個範例很單純,當你訪問http://localhost:3000/ping
,頁面上會得到:
{
message: "pong"
}
算是一個單純的API範例,我想go真的很適合用來作為api server,也因此範例也選擇api。
Gin的路由設計可以實現restful風格,所以常見的幾種action都支援:
router := gin.Default()
router.GET("/someGet", getting)
router.POST("/somePost", posting)
router.PUT("/somePut", putting)
router.DELETE("/someDelete", deleting)
router.PATCH("/somePatch", patching)
router.HEAD("/someHead", head)
router.OPTIONS("/someOptions", options)
參數的部分,通過gin.Context
來擷取:
router.GET("/string/:name", func(c *gin.Context) {
name := c.Param("name")
fmt.Println("Hello %s", name)
})
另外也可以設計為路由群組,達到類似rails的scope效果:
someGroup := router.Group("/someGroup")
{
someGroup.GET("/someGet", getting)
someGroup.POST("/somePost", posting)
}
這麼有趣的框架只講一天好像有點可惜,但沒辦法只好鐵人賽後有機會繼續研究吧!