通过embed 包可以在go应用程序运行时访问嵌入的文件,go1.16功能
在import "embed" 后的Go源文件可以使用// go:embed
指令在编译时从包目录或子目录读取文件内容来初始化string、[]byte或FS类型的变量。
例如,以下三种方法可嵌入名为hello.txt的文件,然后在运行时打印其内容:
import "embed"//go:embed hello.txtvar s stringprint(s)//go:embed hello.txtvar b []byteprint(string(b))//go:embed hello.txtvar f embed.FSdata, _ := f.ReadFile("hello.txt")print(string(data))
变量声明上方的// go:embed指令使用一个或多个path.Match模式指定要嵌入的文件。
该指令必须紧接在包含单个变量声明的行之前。在指令和声明之间仅允许空行和'//'行注释。
该变量的类型必须为string,[]byte或FS。不允许使用命名类型或从这些类型派生的类型别名。
例如:
package serverimport "embed"// content holds our static web server content.//go:embed image/* template/*//go:embed html/index.htmlvar content embed.FS
Go构建系统将识别指令,并安排使用文件系统中的匹配文件填充声明的变量(在上面的示例中为content)
// go:embed
指令为了简洁起见接受多个以空格分隔的模式,但是也可以重复执行此操作,以避免在有许多模式时出现很长的行。模式是相对于包含源文件的软件包目录来解释的。即使在Windows系统上,路径分隔符也是一个正斜杠。为了命名名称中带有空格的文件,可以将模式写为Go双引号或反引号字符串文字。
如果模式命名目录,则以该目录为根的子树中的所有文件都将被嵌入(递归),但文件名以"."开头的文件除外。或'_'排除在外。因此,上面示例中的变量几乎等同于:
// content is our static web server content.//go:embed image template html/index.htmlvar content embed.FS
区别在于,"image/*"嵌入"image/.tempfile",而"image"没有嵌入。
// go:embed
指令可以与导出和未导出的变量一起使用,具体取决于软件包是否希望使数据可用于其他软件包。同样,它可以与全局变量和局部函数一起使用,这取决于上下文中更方便的方法。
模式不得与包模块外部的文件匹配,例如".git/*"或符号链接。空目录的匹配将被忽略。之后,// go:embed行中的每个模式必须至少匹配一个文件或非空目录。
模式不得包含"." 或".."路径元素也不能以斜杠开头。要匹配当前目录中的所有内容,请使用"*"而不是"."。
如果任何模式无效或匹配无效,则构建将失败。
类型为string或[]byte的变量的// go:embed
行只能有一个模式,该模式只能与一个文件匹配。Strings或[]byte用该文件的内容初始化。
// go:embed
指令即使使用String或[]byte也需要导入"embed"。在不引用embed.FS的源文件中,使用空白导入(import _"embed")。
为了嵌入单个文件,通常最好使用string或[]byte类型的变量。FS类型可以嵌入文件树,例如上面的示例中的静态Web服务器内容目录。
FS实现io/fs包的FS接口,因此它可以与任何了解文件系统的包一起使用,包括net/http,text/template和html/template。
例如,给定上面示例中的content变量,我们可以编写:
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(content))))template.ParseFS(content, "*.tmpl")
•创建test项目
mkdir testcd testgo mod init test
•创建静态资源
mkdir staticecho "hello world" > index.html
•测试嵌入资源
1.string模式
package mainimport ( _ "embed" "net/http")//go:embed static/index.htmlvar static stringfunc main() { r := http.NewServeMux() r.HandleFunc("/", echo) srv := &http.Server{ Handler: r, Addr: "localhost:8080", } srv.ListenAndServe()}func echo(w http.ResponseWriter, r *http.Request) { w.Write([]byte(static))}
测试
curl http://localhost:8080/static/
1.fs 模式
package mainimport ( "embed" "net/http")//go:embed staticvar static embed.FSfunc main() { r := http.NewServeMux() //r.HandleFunc("/", echo) webapp := http.FileServer(http.FS(static)) r.Handle("/",webapp) srv := &http.Server{ Handler: r, Addr: "localhost:8080", } srv.ListenAndServe()}
测试
curl http://localhost:8080/static/index2.html