上週跟 Gin 作者 @javierprovecho 討論要發佈新版本,很快地經過一兩天,作者終於整理好 v1.2 版本,除了釋出新版本外,也換了有顏色的 Logo,真心覺得很好看。大家來看看 v1.2 釋出哪些功能,或修正哪些問題。
如何升級
首先來看看如何升級版本,建議還沒有用 vendor 工具的開發者,是時候該導入了。底下可以透過 govender 來升級 Gin 框架。$ govendor fetch github.com/gin-gonic/gin@v1.2 $ govendor fetch github.com/gin-gonic/gin/render由於我們新增
Template Func Maps
,所以 render
套件也要一併升級喔。
從 godeps 轉換到 govender
Gin 專案本來是用 godeps,但是在套件處理上有些問題,所以我們決定換到穩定些的 govender,看看之後 Go 團隊開發的 dep 可不可以完全取代掉 govendor。支援 Let’s Encrypt
我另外開一個專案 autotls 讓 Gin 也可以支援 Let’s Encrypt,這專案可以用在 net/http 套件上,所以基本上支援全部框架,除非搭建的 Http Server 不是用 net/http。使用方式很簡單,如下:用一行讓 Web 支援 TLS
package main import ( "log" "github.com/gin-gonic/autotls" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() // Ping handler r.GET("/ping", func(c *gin.Context) { c.String(200, "pong") }) log.Fatal(autotls.Run(r, "example1.com", "example2.com")) }
自己客製化 Auto TLS Manager
開發者可以將憑證存放在別的目錄,請修改/var/www/.cache
package main import ( "log" "github.com/gin-gonic/autotls" "github.com/gin-gonic/gin" "golang.org/x/crypto/acme/autocert" ) func main() { r := gin.Default() // Ping handler r.GET("/ping", func(c *gin.Context) { c.String(200, "pong") }) m := autocert.Manager{ Prompt: autocert.AcceptTOS, HostPolicy: autocert.HostWhitelist("example1.com", "example2.com"), Cache: autocert.DirCache("/var/www/.cache"), } log.Fatal(autotls.RunWithManager(r, &m)) }
支援 Template Func 功能
首先讓開發者可以調整 template 分隔符號,原本是用{{
及 }}
,現在可以透過 Gin 來設定客製化符號。
r := gin.Default() r.Delims("{[{", "}]}") r.LoadHTMLGlob("/path/to/templates"))另外支援 Custom Template Funcs
... func formatAsDate(t time.Time) string { year, month, day := t.Date() return fmt.Sprintf("%d/%02d/%02d", year, month, day) } ... router.SetFuncMap(template.FuncMap{ "formatAsDate": formatAsDate, }) ... router.GET("/raw", func(c *Context) { c.HTML(http.StatusOK, "raw.tmpl", map[string]interface{}{ "now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC), }) }) ...打開
raw.tmpl
寫入
Date: {[{.now | formatAsDate}]}執行結果:
Date: 2017/07/01
增加 Context 函式功能
在此版發佈前,最令人煩惱的就是 Bind Request Form 或 JSON 驗證,因為 Gin 會直接幫忙回傳 400 Bad Request,很多開發者希望可以自訂錯誤訊息,所以在 v1.2 我們將BindWith
丟到 deprecated 檔案,並且打算在下一版正式移除。
// BindWith binds the passed struct pointer using the specified binding engine. // See the binding package. func (c *Context) BindWith(obj interface{}, b binding.Binding) error { log.Println(`BindWith(\"interface{}, binding.Binding\") error is going to be deprecated, please check issue #662 and either use MustBindWith() if you want HTTP 400 to be automatically returned if any error occur, of use ShouldBindWith() if you need to manage the error.`) return c.MustBindWith(obj, b) }如果要自訂訊息,請用
ShouldBindWith
package main import ( "github.com/gin-gonic/gin" ) type LoginForm struct { User string `form:"user" binding:"required"` Password string `form:"password" binding:"required"` } func main() { router := gin.Default() router.POST("/login", func(c *gin.Context) { // you can bind multipart form with explicit binding declaration: // c.MustBindWith(&form, binding.Form) // or you can simply use autobinding with Bind method: var form LoginForm // in this case proper binding will be automatically selected if c.ShouldBindWith(&form) == nil { if form.User == "user" && form.Password == "password" { c.JSON(200, gin.H{"status": "you are logged in"}) } else { c.JSON(401, gin.H{"status": "unauthorized"}) } } }) router.Run(":8080") }大致上是這些大修正,剩下的小功能或修正,請直接參考 v1.2 releases log。