Go 語言框架 Gin 終於發佈 v1.2 版本

19807878_1634683919888714_743883353_o 上週跟 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
  • 博主你好,請問 Gin 怎麽實現在開發環境修改代碼然後自動重載代碼呢?個人對測試驅動開發還不是很好的掌握,現在感覺每次自動重啓很浪費時間。