jinzh notes
jinzh notes

Go内嵌文件

Go内嵌文件
内容纲要

前言

Go编译的程序非常适合部署,如果没有通过CGO引用其它的库的话,我们一般编译出来的可执行二进制文件都是单个的文件,非常适合复制和部署。在实际使用中,除了二进制文件,可能还需要一些配置文件,或者静态文件,比如html模板、静态的图片、CSS、javascript等文件,golang团队为此也制定了一个非常简易的api来将文件内嵌到其中。

嵌入特性

  • 支持单文件嵌入为string和[]byte
  • 支持将文件及文件夹嵌入为文件系统FS
  • 隐式使用,匿名引入embed
  • 仅一行指令go:embed实现嵌入

嵌入示例

go将文件嵌入后是打包在编译出的二进制文件中的,所以文件仅支持读取和遍历,这也意味着它是线程安全的

以下为嵌入使用示例,

嵌入为string

比如当前文件下有个hello.txt的文件,文件内容为hello,world!。通过 go:embed 指令,在编译后下面程序中的s变量的值就变为了hello,world!。

package main
import (
    _ "embed"
    "fmt"
)
//go:embed hello.txt
var s string
func main() {
    fmt.Println(s)
}

嵌入为[]byte

这里不多赘述,参见下面:

package main
import (
    _ "embed"
    "fmt"
)
//go:embed hello.txt
var b []byte
func main() {
    fmt.Println(b)
}

嵌入为fs.FS

go提供了这个包来将文件内嵌为一个fs文件系统,专为嵌入文件夹所用!

package main
import (
    "embed"
    "fmt"
)

# 嵌入多个文件、子文件、文件夹
//go:embed hello.txt
//go:embed hello2.txt
//go:embed p/hello2.txt
//go:embed p
# 以上也可以写成一行,如 //go:embed hello.txt hello2.txt
var f embed.FS
func main() {
    data, _ := f.ReadFile("hello.txt")
    fmt.Println(string(data))
    #读取文件夹中文件
    data, _ := f.ReadFile("p/hello.txt")
    fmt.Println(string(data))
    data, _ = f.ReadFile("p/hello2.txt")
    fmt.Println(string(data))
}

注意

go:embed 指令中可以只写文件夹名,此文件夹中除了.和_开头的文件和文件夹都会被嵌入,并且子文件夹也会被递归的嵌入,形成一个此文件夹的文件系统。

如果想嵌入.和_开头的文件和文件夹, 比如p文件夹下的.hello.txt文件,那么就需要使用*,比如go:embed p/*

不具有递归性,所以子文件夹下的.和_不会被嵌入,除非你在专门使用子文件夹的进行嵌入

template也可以从嵌入的文件系统中解析模板

影翼

文章作者

发表评论

textsms
account_circle
email

jinzh notes

Go内嵌文件
Go编译的程序非常适合部署,如果没有通过CGO引用其它的库的话,我们一般编译出来的可执行二进制文件都是单个的文件,非常适合复制和部署。在实际使用中,除了二进制文件,可能还需要一些配置文件,或者静态文件,比如html模板、静态的图片、CSS、javascript等文件,如何这些文件也能打进到二进制文件中,那就太美妙,我们只需复制、按照单个的可执行文件即可。
扫描二维码继续阅读
2022-05-04