英文:
How can I embed hidden file in Go?
问题
我想使用Go语言的embed包来嵌入隐藏文件,比如git信息。
例如:
package main
import _ "embed"
var (
//go:embed .git/HEAD
head string
)
func main() {
print(head)
}
但是会出现编译错误。
$ go build
main.go:6:13: pattern .git/HEAD: cannot embed file .git/HEAD: in invalid directory .git
我尝试了以下方法,但都没有成功:
- 创建符号链接并嵌入该链接
- 使用转义字符并用双引号括起来
添加内容
"files outside the package's module" 是什么意思?
它听起来与 go-modules 无关。
为什么下面的文件是可以的,但是.git/*
不可以?
$ mkdir .hidden && echo "hello world" > .hidden/hello.txt
$ tree -a
.
|-- .hidden
| `-- hello.txt <- 是包的模块吗?
|-- go.mod
|-- go_embed_git_version
`-- main.go
.git/HEAD
和 .hidden/hello.txt
有什么区别?
英文:
I want to embed hidden file, with embed package in Go. Such as git info.
For example
package main
import _ "embed"
var (
//go:embed .git/HEAD
head string
)
func main() {
print(head)
}
But it occure compile error.
$ go build
main.go:6:13: pattern .git/HEAD: cannot embed file .git/HEAD: in invalid directory .git
I tried those way, but didn't work.
- Make symbolic link and embed that
- Escaping and wrap with double quotes
<br/>
added
What does means files outside the package's module
exactly?
It sounds like not about go-modules.
Why below file is OK but not .git/*
?
$ mkir .hidden && echo "hello world" > .hidden/hello.txt
$ tree -a
.
|-- .hidden
| `-- hello.txt <- is package's module ?
|-- go.mod
|-- go_embed_git_version
`-- main.go
What is difference between .git/HEAD
and .hidden/hello.txt
?
答案1
得分: 3
这种行为在官方文档中有明确说明:
> 模式不能匹配包的模块之外的文件,比如.git/*
或符号链接。空目录的匹配会被忽略。之后,在//go:embed
行中的每个模式都必须至少匹配一个文件或非空目录。
更好的方法是通过在go build
命令行中包含提交 ID,例如在这里描述的方式。如果你的代码如下所示:
package main
import "fmt"
var (
head string = "development"
)
func main() {
fmt.Println(head)
}
然后使用以下命令构建二进制文件:
go build -ldflags "-X main.head=$(git rev-parse HEAD)"
运行代码将打印构建代码时的 HEAD 提交 ID。
通常可以在Makefile
中自动化这种操作,例如:
COMMITID = $(shell git rev-parse HEAD)
GOLDFLAGS = -X 'main.head=$(COMMITID)'
all: example
example: main.go
go build -ldflags "$(GOLDFLAGS)"
clean:
rm -f example
然后只需输入make
即可使用正确的命令行标志构建二进制文件。
英文:
That behavior is explicitly documented:
> Patterns must not match files outside the package's module, such as .git/*
or symbolic links. Matches for empty directories are ignored. After that, each pattern in a //go:embed
line must match at least one file or non-empty directory.
A better way of getting the commit id into your code is by including it on the go build
command line, as described for example here. If your code looks like this:
package main
import "fmt"
var (
head string = "development"
)
func main() {
fmt.Println(head)
}
And you build your binary like this:
go build -ldflags "-X main.head=$(git rev-parse HEAD)"
Then running your code would print the HEAD commit id from when the
code was built.
It's common to automate this sort of thing in a Makefile
, something
like:
COMMITID = $(shell git rev-parse HEAD)
GOLDFLAGS = -X 'main.head=$(COMMITID)'
all: example
example: main.go
go build -ldflags "$(GOLDFLAGS)"
clean:
rm -f example
Then you just type make
to build the binary with the correct command
line flags.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论