Go 語言 官方維護團隊 rsc 之前在 GitHub Issue 上面提出要在 go command line 直接支援 Embedding Files,沒想到過沒幾個月,就直接實現出來了,並且預計在 2021 的 go 1.16 版本直接支援 embed 套件 。有了這個功能,就可以將靜態檔案或專案設定檔直接包起來,這樣部署就更方便了。底下來看看官方怎麼使用。
影片教學 VIDEO
如果對於課程內容有興趣,可以參考底下課程。
如果需要搭配購買請直接透過 FB 聯絡我 ,直接匯款(價格再減 100 )
embed package 直接看官方給的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main
import (
"embed"
)
//go:embed hello.txt
var s string
//go:embed hello.txt
var b []byte
//go:embed hello.txt
var f embed.FS
func main () {
print (s)
print (string (b))
data, _ := f.ReadFile ("hello.txt" )
print (string (data))
}
可以看到關鍵字: go:embed
,透過註解就可以將靜態檔案直接使用在開發上面,另外也可以引用多個檔案或多個目錄:
1
2
3
4
5
6
7
8
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 時加上 _
,範例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
import _ "embed"
//go:embed hello.txt
var s string
//go:embed hello.txt
var b []byte
func main () {
print (s)
print (string (b))
}
有了這個 Package 後,再也不需要第三方套件 Resource Embedding 了,底下來看看如何將 embed 套件整合進 Gin ?
整合 Gin Framework 先假設 Gin 需要包含靜態圖片及 Template,底下是目錄結構:
1
2
3
4
5
6
7
8
9
10
11
├── assets
│ ├── favicon.ico
│ └── images
│ └── example.png
├── go.mod
├── go.sum
├── main.go
└── templates
├── foo
│ └── bar.tmpl
└── index.tmpl
該如何將 Template 跟 assets 目錄直接打包進 Go 呢?直接看 main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package main
import (
"embed"
"html/template"
"net/http"
"github.com/gin-gonic/gin"
)
//go:embed assets/* templates/*
var f embed.FS
func main () {
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" )
}
開發者可以很簡單用兩行就將靜態檔案直接包進來:
1
2
//go:embed assets/* templates/*
var f embed.FS
靜態檔案的 route 可以直接透過底下設定:
1
2
// example: /public/assets/images/example.png
router.StaticFS ("/public" , http.FS (f))
也可以透過 ReadFile
讀取單一檔案:
1
2
3
4
5
6
7
8
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 了。
See also