很长一段时间以来,我一直想知道在哪里为我的go包保存资源,我找不到正确的答案。
目前,资源保留在
中当我从main使用go run *.go
时,它运行正常。但是,当我运行测试时,无法找到资源,因为Go会将当前工作目录更改为相应的模块。一个解决方法是只使用os.Chdir('..'),但每次测试都这样做有点令人讨厌。此外,有时在包初始化时加载资源。这意味着有一个包含所有模板(及其相应名称)的全局地图:
package module2
var myTemplates = map[string]template { "index": loadTemplateFromFile() }
我知道你不应该因为并发而使用全局变量,但是这个变量对于并发读取是安全的(并且它只在启动时写入)。因此,我将模板放入全局变量中,以便在启动时加载它们,并在启动期间捕获一些错误,并且模板已经在内存中。
这意味着我无法及时更改工作目录,因为问题已经出现错误,并且错误告诉我无法找到该文件(这是我想要的确切行为)。
后来,我发现了一个方法runtime.Caller
来获取编译go文件的路径(如果可用):
base := "."
if _, filename, _, ok := runtime.Caller(0); ok {
base = path.Join(path.Dir(filename), "..")
}
file := path.Join(base, "module1", "resources", ...)
现在,所有测试都运行正常,go run *.go
也找到了正确的资源。一旦我开始部署我的包,这个方法就成了问题。因为runtime.Caller使用编译期间使用的路径,所以我必须将资源放在我编写它们的精确相同的位置。这意味着当我在/home/matt3o12/go/src/domain.tld/matt3o12/mypackage
中构建二进制文件时,我必须将所有资源文件夹放在服务器上完全相同的路径上。
我也尝试使用os.Executable
,但这是毫无意义的,因为它只是指向内部编译可执行文件的一些临时路径(并且没有资源)。除非我编译测试包并手动运行,否则这非常紧张。
我也不希望将资源存储在二进制文件中(具有项目资源的文件夹结构就好了)。
我确实有一些想法可以解决这个问题,但我认为其中任何一个都不是可选的:
go test ./...
或go run *.go
时,我都要担心正确的资源路径。)不是重复:
答案 0 :(得分:0)
没有“应该”。你可以把它们放在你认为合适的地方。如果你愿意,你可以嵌入它们。最简单的方法可能是使您的资源路径可以使用一些合理的默认值进行配置(例如默认为“。”或runtime.Caller(0)
。