最近需要使用 golang1.16 中的功能 embed ,本文简单记录下 embed 的使用。
embed 介绍#
Go 1.16 引入了embed包,允许我们在编译时将静态文件(例如 .go、.html、.css、.js 等)嵌入到 Go 源文件中。这在构建静态网站、单页应用程序(SPA)和其他项目时非常有用。
主要有几个优点:
嵌入为字符串#
可以将文件内容保存到字符串变量中。
1
2
3
4
5
6
7
8
9
10
11
12
13
| package main
import (
_ "embed"
"fmt"
)
//go:embed hello.txt
var s string
func main() {
fmt.Println(s)
}
|
文件路径下有个 hello.txt,内容如下:hello, overstarry
,代码运行输出:hello, overstarry
保存为 []bytes#
还可以将文件内容保存为 []bytes变量
1
2
3
4
5
6
7
8
9
10
11
12
13
| package main
import (
_ "embed"
"fmt"
)
//go:embed hello.txt
var s []byte
func main() {
fmt.Println(string(s))
}
|
运行代码输出内容与上面一致。
保存为 fs.FS 类型#
还可以将文件保存为 fs.FS 类型,这在嵌入多个文件时非常有用(string和[]bytes不支持多个//go:embed指令)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| package main
import (
"embed"
"fmt"
)
//go:embed hello.txt
//go:embed hello2.txt
var f embed.FS
func main() {
data, _ := f.ReadFile("hello.txt")
fmt.Println(string(data))
data, _ = f.ReadFile("hello2.txt")
fmt.Println(string(data))
}
|
嵌入的内容是只读的。也就是在编译期嵌入文件的内容是什么,那么在运行时的内容也就是什么。
FS文件系统值提供了打开和读取的方法,并没有write的方法,也就是说FS实例是线程安全的,多个goroutine可以并发使用。
单个文件嵌入为多个变量#
还可以将单个文件保存为多个变量。
1
2
3
4
5
6
7
8
9
10
11
12
13
| package main
import (
_ "embed"
"fmt"
)
//go:embed hello.txt
var s string
//go:embed hello.txt
var s2 string
func main() {
fmt.Println(s)
fmt.Println(s2)
}
|
将 hello.txt的内容保存为 s和s2变量以供不同地方使用。
文件嵌入为可导出变量#
可以将文件嵌入为可导出变量和不可导出变量,以应对需要外部调用的场景。
1
2
3
4
5
6
7
8
9
10
11
12
13
| package main
import (
_ "embed"
"fmt"
)
//go:embed hello.txt
var S string
//go:embed hello.txt
var s2 string
func main() {
fmt.Println(S)
fmt.Println(s2)
}
|
嵌入多个文件#
go:embed指令支持嵌入多个文件
1
2
3
4
5
6
7
8
9
10
11
12
13
| package main
import (
"embed"
"fmt"
)
//go:embed hello.txt hello2.txt
var f embed.FS
func main() {
data, _ := f.ReadFile("hello.txt")
fmt.Println(string(data))
data, _ = f.ReadFile("hello2.txt")
fmt.Println(string(data))
}
|
嵌入文件夹#
除了支持文件嵌入还可以嵌入整个文件夹。需要注意的是文件夹分隔符使用/
,windows环境也是。
1
2
3
4
5
6
7
8
9
10
11
12
13
| package main
import (
"embed"
"fmt"
)
//go:embed p
var f embed.FS
func main() {
data, _ := f.ReadFile("p/hello.txt")
fmt.Println(string(data))
data, _ = f.ReadFile("p/hello2.txt")
fmt.Println(string(data))
}
|
除了上面介绍的一些功能,embed还支持相对路径等功能,感兴趣的读者可以自行查阅相关资料。