2

Go 1.16 推出 Embedding Files

 3 years ago
source link: https://blog.wu-boy.com/2020/12/embedding-files-in-go-1-16/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Go 語言官方維護團隊 rsc 之前在 GitHub Issue 上面提出要在 go command line 直接支援 Embedding Files,沒想到過沒幾個月,就直接實現出來了,並且預計在 2021 的 go 1.16 版本直接支援 embed 套件。有了這個功能,就可以將靜態檔案或專案設定檔直接包起來,這樣部署就更方便了。底下來看看官方怎麼使用。

如果對於課程內容有興趣,可以參考底下課程。

如果需要搭配購買請直接透過 FB 聯絡我,直接匯款(價格再減 100

embed package

直接看官方給的例子:

package main

import "embed"

func main() {
    //go:embed hello.txt
    var s string
    print(s)

    //go:embed hello.txt
    var b []byte
    print(string(b))

    //go:embed hello.txt
    var f embed.FS
    data, _ := f.ReadFile("hello.txt")
    print(string(data))

}

可以看到關鍵字: go:embed,透過註解就可以將靜態檔案直接使用在開發上面,另外也可以引用多個檔案或多個目錄:

package server

import "embed"

// content holds our static web server content.
//go:embed image/* template/*
//go:embed html/index.html
var content embed.FS

可以看到 go:embed 支援多個目錄,單一檔案或多個檔案都可以,假如沒有用到 embed.FS,請在 import 時加上 _,範例如下:

package main

import _ "embed"

func main() {
    //go:embed hello.txt
    var s string
    print(s)

    //go:embed hello.txt
    var b []byte
    print(string(b))
}

有了這個 Package 後,再也不需要第三方套件 Resource Embedding 了,底下來看看如何將 embed 套件整合進 Gin

整合 Gin Framework

先假設 Gin 需要包含靜態圖片及 Template,底下是目錄結構:

├── assets
│   ├── favicon.ico
│   └── images
│       └── example.png
├── go.mod
├── go.sum
├── main.go
└── templates
    ├── foo
    │   └── bar.tmpl
    └── index.tmpl

該如何將 Template 跟 assets 目錄直接打包進 Go 呢?直接看 main.go

package main

import (
    "embed"
    "html/template"
    "net/http"

    "github.com/gin-gonic/gin"
)

func main() {
    //go:embed assets/* templates/*
    var f embed.FS

    router := gin.Default()
    templ := template.Must(template.New("").ParseFS(f, "templates/*.tmpl", "templates/foo/*.tmpl"))
    router.SetHTMLTemplate(templ)

    // example: /public/assets/images/example.png
    router.StaticFS("/public", http.FS(f))

    router.GET("/", func(c *gin.Context) {
        c.HTML(http.StatusOK, "index.tmpl", gin.H{
            "title": "Main website",
        })
    })

    router.GET("/foo", func(c *gin.Context) {
        c.HTML(http.StatusOK, "bar.tmpl", gin.H{
            "title": "Foo website",
        })
    })

    router.GET("favicon.ico", func(c *gin.Context) {
        file, _ := f.ReadFile("assets/favicon.ico")
        c.Data(
            http.StatusOK,
            "image/x-icon",
            file,
        )
    })

    router.Run(":8080")
}

開發者可以很簡單用兩行就將靜態檔案直接包進來:

//go:embed assets/* templates/*
var f embed.FS

靜態檔案的 route 可以直接透過底下設定:

// example: /public/assets/images/example.png
router.StaticFS("/public", http.FS(f))

也可以透過 ReadFile 讀取單一檔案:

router.GET("favicon.ico", func(c *gin.Context) {
    file, _ := f.ReadFile("assets/favicon.ico")
    c.Data(
        http.StatusOK,
        "image/x-icon",
        file,
    )
})

程式範例可以直接在這邊找到

Go 團隊真的蠻用心的,會比一些常用核心的功能納入官方維護,以保持後續的更新,有了這項功能,在 Go 的部署流程,直接可以略過靜態檔案加入 Docker 內了。未來專案有些保密檔案也可以透過此方式直接在 CI 流程內先換掉,再進行 go build 了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK