The Go Language official maintenance team, rsc, previously proposed in the GitHub Issue to support Embedding files directly in the go command line. Files, I didn’t expect that in a few months, it was directly implemented, and in the 2021 go 1.16 version directly support embed package. With this feature, static files or project configuration files can be wrapped up directly, which makes deployment easier. Here’s how to use it officially.

embed package

See the official example directly:

 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))
}

You can see the keyword: go:embed, through the annotation you can use the static file directly in the development of the above, in addition, you can also refer to multiple files or multiple directories:

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

You can see that go:embed supports multiple directories, single file or multiple files. If you don’t use embed.FS, please add _ to the import, for example:

 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))
}

With this Package, you no longer need a Third Party Package Resource Embedding , to see how to integrate the embed package into Gin?

Integrating Gin Framework

Let’s assume that Gin needs to contain static images and Template, the following is the directory structure:

 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

How do I package Template and assets directories into Go? Look directly at 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")
}

Developers can simply wrap static files in two lines:

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

The route for static files can be set directly from the bottom:

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

You can also read a single file with 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,
    )
})

Program examples can be found directly at here.

Summary

The Go team is really dedicated and will include some common core features in the official maintenance to keep it up to date. With this feature, you can skip the static files and add them to Docker directly in the Go deployment process. In the future, some confidential files of the project can be replaced directly in the CI process and then go build.