Go:将静态文件嵌入二进制文件中

4

1
请参见https://dev59.com/w4Xca4cB1Zd3GeqPGk8p#27010732。 - VonC
2个回答

9

在5/6年后,随着Go 1.16(2021年第一季度)的发布,使用嵌入文件将变得更加容易。Go 1.16支持嵌入文件 (issue/proposal 41191)

可以使用//go:embed指令来命名单个文件,并初始化一个普通的string[]byte变量:

//go:embed gopher.png
var gopherPNG []byte

导入语句是必需的,用于将文件标记为包含//go:embed行并需要处理。
可以通过让Goimports(以及gopls等)学习此规则,并在需要时自动添加任何带有//go:embed的文件中来实现该功能。
这引发了有关如何避免在使用//go:embed时意外包含“隐藏”文件的讨论,详见issue 42328
这在CL 275092commit 37588ff中解决了。

决定从嵌入整个目录树时排除与.*_*匹配的文件。

请参见src/embed/internal/embedtest/embed_test.go
    //go:embed testdata/k*.txt
    var local embed.FS
    testFiles(t, local, "testdata/ken.txt", "If a program is too slow, it must have a loop.\n")

    //go:embed testdata/k*.txt
    var s string
    testString(t, s, "local variable s", "If a program is too slow, it must have a loop.\n")

    //go:embed testdata/h*.txt
    var b []byte
    testString(t, string(b), "local variable b", "hello, world\n")

注意:自CL 281492起,如果支持,cmd/go将传递embedcfggccgo
另请参见(2021年1月)问题43854,“选择加入//go:embed以不忽略文件和空目录”。

4

假设有以下目录结构:

example/
    main.go
    data/hi.html

example/main.go

package main

import (
    "html/template"
    "log"
    "net/http"
    "os"
)

var tmpl *template.Template

func init() {
    data, err := Asset("data/hi.html")
    if err != nil {
        log.Fatal(err)
    }
    tmpl = template.Must(template.New("tmpl").Parse(string(data)))
}

func main() {
    // print to stdout
    tmpl.Execute(os.Stdout, map[string]string{"Name": "James"})

    http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        tmpl.Execute(w, map[string]string{"Name": "James"})
    })

    log.Fatal(http.ListenAndServe(":8000", nil))
}

example/data/hi.html

<h1>Hi, {{.Name}}</h1>

按如下方式运行:

go-bindata data && go build && ./example

控制台输出:

<h1>Hi, James</h1>

HTTP output:

Hi, James


谢谢!关于提供JS文件怎么办?我试图将它们以结构形式传递到tmpl.Execute中的HTML模板中。我得到的JS错误是这样的:GET http://localhost:8000/*!%20jQuery%20v2.1.3%20%7c%20%28c%29%202005,%202014%2…%7c[%5c%5cw-]%7c[%5e%5c%5cx00-%5c%5cxa0]%29+%22,N=M.replace%28%22w%22,%22w - user3918985
@user3918985,看起来你的JS文件被HTML模板转义了。如果你只想从二进制文件中提供文件内容,你不需要使用html/template,只需提供从Asset函数获取的内容即可。在HandleFunc中,你可以使用w http.ResponseWriter将Asset数据写出,例如w.Write(data) - jmaloney
哇..但我必须逐个写入每个数据吗?还是可以将它们放在一个目录中?我现在正在尝试。 - user3918985
嗯,我得到了整个文件内容在页面上打印出来的结果。我正在尝试编写CSS文件。 - user3918985
我在这里发布了另一个问题:http://stackoverflow.com/questions/27903565/go-embed-js-files-with-bindata?noredirect=1#comment44209499_27903565 - user3918985

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接