英文:
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 275092和commit 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 (
"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>
run like so:
go-bindata data && go build && ./example
Console Output:
<h1>Hi, James</h1>
HTTP output:
<h1>Hi, James</h1>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论