Golang - 应该保留资源

时间:2017-07-04 23:22:03

标签: go resources

很长一段时间以来,我一直想知道在哪里为我的go包保存资源,我找不到正确的答案。

目前,资源保留在

  • 主/模块1 /资源
  • 主/模块2 /资源

当我从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时,我都要担心正确的资源路径。)
  • 使用“magic”来确定是否运行测试并更改路径。我不愿意使用它,因为我必须将这些检查放在我的代码上,我讨厌有很多“边缘/特殊”的情况。

不是重复:

1 个答案:

答案 0 :(得分:0)

没有“应该”。你可以把它们放在你认为合适的地方。如果你愿意,你可以嵌入它们。最简单的方法可能是使您的资源路径可以使用一些合理的默认值进行配置(例如默认为“。”或runtime.Caller(0)