go:embed功能简化了在Go应用程序中包含静态资源的过程。通过在编译时嵌入文件和目录,您可以创建更便携和自包含的二进制文件。
随着 Go 1.16[1] 的发布,go:embed
被引入。这个新的代码注释(我们称之为指令)允许您将静态文件和文件夹嵌入到Go二进制文件中。如果您正在构建需要提供静态内容的Web服务器或需要配置文件的命令行工具,go:embed
通过消除对外部文件处理的需求来简化这个过程。这也意味着您的二进制文件包含了发布代码所需的一切。非常强大!
什么是go:embed?
go:embed
指令告诉Go编译器在构建时将文件和文件夹包含到编译后的二进制文件中。这意味着您的应用程序可以直接从内存访问这些资源,而无需在运行时从磁盘读取。
要使用go:embed,您需要Go 1.16或更高版本。以下是如何嵌入单个文件的简单示例:
首先,创建一个名为message.txt
的文本文件。它可以包含任何内容 - 比如:
hello from bytesizego!
然后在main.go
中编写以下代码
package main import ( _ "embed" "fmt" ) //go:embed message.txt var message string func main() { fmt.Println(message) }
在这个非常小的程序中,我们:
• 导入embed包的空白标识符_以启用go:embed
指令。
• 使用//go:embed message.txt
指令指定要嵌入的文件。
• 添加一个message变量来保存message.txt的内容作为字符串。
正如您所期望的,这个程序输出:
hello from bytesizego!
嵌入多个文件
让我们稍微复杂一点:
package main import ( "embed" "fmt" ) //go:embed messages/* var messages embed.FS func main() { files, _ := messages.ReadDir("messages") for _, file := range files { data, _ := messages.ReadFile("messages/" + file.Name()) fmt.Printf("File: %s\nContent: %s\n\n", file.Name(), string(data)) } }
这里:
• 我们使用embed.FS
来嵌入多个文件。
• ReadDir
和ReadFile
方法允许我们与嵌入的文件交互。
嵌入目录
您还可以嵌入整个文件夹:
package main import ( "embed" "fmt" ) //go:embed static/* var staticFiles embed.FS func main() { data, _ := staticFiles.ReadFile("static/index.html") fmt.Println(string(data)) }
提示: 在嵌入目录时,ReadFile
中指定的路径是相对于嵌入根目录的。
使用go embed创建Web应用
非常简单!
package main import ( "embed" "net/http" ) //go:embed static/* var staticFiles embed.FS func main() { http.Handle("/", http.FileServer(http.FS(staticFiles))) http.ListenAndServe(":8080", nil) }
运行程序,现在您可以通过 http://localhost:8080/[2] 访问您嵌入的静态文件。
使用go embed将文件嵌入到结构体中
也许您想嵌入一些内容以便稍后在程序中使用。将它放在结构体上可能是您想要的。这对于配置可能很有用。
package main import ( "embed" "fmt" ) //go:embed templates/home.html var homeTemplate string //go:embed templates/about.html var aboutTemplate string type Templates struct { Home string About string } func main() { t := Templates{ Home: homeTemplate, About: aboutTemplate, } fmt.Println("Home Template:", t.Home) fmt.Println("About Template:", t.About) }
使用go Embed嵌入图像和PDF
如果您正在处理非文本文件(如图像或PDF),您应该使用字节切片:
package main import ( _ "embed" "fmt" ) //go:embed image.jpg var imageData []byte func main() { fmt.Printf("Image size: %d bytes\n", len(imageData)) }
对此要小心!这里有一些限制:
- 文件大小: 嵌入大文件可能会显著增加您的二进制文件大小。
- 文件更改: 对嵌入文件的更改需要重新编译。
总结
go embed非常棒!我很少看到它被使用,但现在我经常使用它,特别是在创建Web应用时。
参考链接
- Go 1.16: https://go.dev/doc/go1.16
- http://localhost:8080/
- 我们的其他博客: https://www.bytesizego.com/blog
- 加入我们的邮件列表: https://www.bytesizego.com/golang-jobs