在Go语言中,可以将静态文件嵌入到二进制文件中。

huangapple go评论87阅读模式
英文:

Go: embed static files in binary

问题

这可能是一个非常初级的问题。我正在尝试将静态文件嵌入到二进制文件中,例如HTML。我该如何使用https://github.com/jteeuwen/go-bindata来实现这一点?

我可以使用https://github.com/jteeuwen/go-bindata#accessing-an-asset来访问资源,但是对于"data"我该怎么处理?我该如何解析文件、执行模板并在目录中提供它们?

我在网上找不到任何示例,希望能得到一些帮助!

英文:

This might be a very amateur question. I'm trying to embed static files into binary, ie. html. How do I do that with https://github.com/jteeuwen/go-bindata?

So I can access an asset with this https://github.com/jteeuwen/go-bindata#accessing-an-asset, but what do I do with "data", and how to do I parse files, execute template, and serve them in the directory?

I couldn't find any examples online, and will appreciate some help!

答案1

得分: 9

5/6年后,使用Go 1.16(2021年第一季度)应该会更容易,因为它增加了对嵌入文件的支持(问题/提案41191)。

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

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

导入语句是必需的,以标记文件包含//go:embed行并需要处理。
Goimports(以及gopls等)可以学习这个规则,并在需要时自动添加导入语句到任何包含//go:embed的文件中。

这引发了关于如何避免在使用//go:embed时意外包含“隐藏”文件的讨论(问题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会将embedcfg传递给gccgo


另请参阅(2021年1月)问题43854,“选择性地使//go:embed不忽略文件和空目录”。

英文:

5/6 years later, this should be easier with Go 1.16 (Q1 2021), which adds support for embedded files (issue/proposal 41191 )

> It will be permitted to use //go:embed naming a single file to initialize a plain string or []byte variable:

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

The import is required to flag the file as containing //go:embed lines and needing processing.
Goimports (and gopls etc) can be taught this rule and automatically add the import in any file with a //go:embed as needed.

That sparked a debate on issue 42328 about how to avoid surprising inclusion of "hidden" files when using //go:embed

This as resolved in CL 275092 and commit 37588ff

> Decision to exclude files matching .* and _* from embedded directory results when embedding an entire directory tree.

See 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")

Note: with CL 281492, cmd/go passes embedcfg to gccgo if supported.


See also (Jan. 2021) issue 43854 "opt-in for //go:embed to not ignore files and empty dirs".

答案2

得分: 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() {
    // 打印到标准输出
    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 输出:

Hi, James

英文:

Given a directory structure like so:

example/
    main.go
    data/hi.html

example/main.go

package main

import (
    &quot;html/template&quot;
    &quot;log&quot;
    &quot;net/http&quot;
    &quot;os&quot;
)

var tmpl *template.Template

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

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

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

    log.Fatal(http.ListenAndServe(&quot;:8000&quot;, nil))
}

example/data/hi.html

&lt;h1&gt;Hi, {{.Name}}&lt;/h1&gt;

run like so:

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

Console Output:

&lt;h1&gt;Hi, James&lt;/h1&gt;

HTTP output:

<h1>Hi, James</h1>

huangapple
  • 本文由 发表于 2015年1月12日 01:11:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/27889779.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定