我有一些从 Go 程序中读取的文本文件。我想发布一个可执行文件,而不额外提供该文本文件。如何将其嵌入到 Windows 和 Linux 上的编译中?
使用go-bindata。从自述文件:
该工具将任何文件转换为可管理的 Go 源代码。用于将二进制数据嵌入到 go 程序中。文件数据在被转换为原始字节切片之前可选地进行 gzip 压缩。
从 2021 年 2 月发布的 Go 1.16 开始,您可以使用以下go:embed指令:
go:embed
import "embed" //go:embed hello.txt var s string print(s) //go:embed hello.txt var b []byte print(string(b)) //go:embed hello.txt var f embed.FS data, _ := f.ReadFile("hello.txt") print(string(data))
从 Go 1.4 开始,如果需要更多灵活性,可以使用go generate
如果您有多个文本文件或文本文件可能会更改,您可能不想对文本文件进行硬编码,而是在编译时将其包含在内。
如果您有以下文件:
main.go scripts/includetxt.go a.txt b.txt
并且想要访问 main.go 中所有 .txt 文件的内容,您可以包含一个包含 go generate 命令的特殊注释。
package main import "fmt" //go:generate go run scripts/includetxt.go func main() { fmt.Println(a) fmt.Println(b) }
go generate 命令将在go:generate. 在这种情况下,它运行一个 go 脚本,该脚本读取所有文本文件并将它们作为字符串文字输出到一个新文件中。我跳过了较短代码的错误处理。
go:generate
package main import ( "io" "io/ioutil" "os" "strings" ) // Reads all .txt files in the current folder // and encodes them as strings literals in textfiles.go func main() { fs, _ := ioutil.ReadDir(".") out, _ := os.Create("textfiles.go") out.Write([]byte("package main \n\nconst (\n")) for _, f := range fs { if strings.HasSuffix(f.Name(), ".txt") { out.Write([]byte(strings.TrimSuffix(f.Name(), ".txt") + " = `")) f, _ := os.Open(f.Name()) io.Copy(out, f) out.Write([]byte("`\n")) } } out.Write([]byte(")\n")) }
将所有 .txt 文件编译到您的可执行文件中:
$ go generate $ go build -o main
现在您的目录结构将如下所示:
main.go main scripts/includetxt.go textfiles.go a.txt b.txt
textfiles.go 是由 go generate 和 script/includetxt.go 生成的
package main const ( a = `hello` b = `world` )
并运行 main 给出
$ ./main hello world
只要您对 UTF8 编码的文件进行编码,这就会正常工作。如果你想编码其他文件,你可以使用 go 语言(或任何其他工具)的全部功能来这样做。我使用这种技术将png:s十六进制编码为单个可执行文件。这需要对 includetxt.go 稍作改动。