How can I embed hidden file in Go?

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

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 _ &quot;embed&quot;

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&#39;s module exactly?

It sounds like not about go-modules.

Why below file is OK but not .git/*?

$ mkir .hidden &amp;&amp; echo &quot;hello world&quot; &gt; .hidden/hello.txt
$ tree -a
.
|-- .hidden
|   `-- hello.txt  &lt;- is package&#39;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 &quot;fmt&quot;

var (
	head string = &quot;development&quot;
)

func main() {
	fmt.Println(head)
}

And you build your binary like this:

go build -ldflags &quot;-X main.head=$(git rev-parse HEAD)&quot;

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 &#39;main.head=$(COMMITID)&#39;

all: example

example: main.go
	go build -ldflags &quot;$(GOLDFLAGS)&quot;

clean:
	rm -f example

Then you just type make to build the binary with the correct command
line flags.

huangapple
  • 本文由 发表于 2021年8月23日 11:32:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/68887004.html
匿名

发表评论

匿名网友

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

确定