【问题标题】:Golang -- where should resources be keptGolang——资源应该存放在哪里
【发布时间】:2017-07-04 23:22:03
【问题描述】:

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

现在,资源被保存到

  • main/module1/resources
  • main/module2/resources

当我只使用 main 中的 go run *.go 时,它工作正常。但是,当我运行测试时,找不到资源,因为 Go 将当前工作目录更改为相应的模块。一种解决方法是只使用 os.Chdir('..') 但对每个测试都这样做似乎有点烦人。此外,有时资源会在包初始化时加载。这意味着有一个包含所有模板(及其相应名称)的全局地图:

package module2

var myTemplates = map[string]template { "index": loadTemplateFromFile() }

我知道你不应该因为并发而在 go 中使用全局变量,但是这个变量对于并发读取是安全的(并且它只在启动期间被写入)。所以我把模板放到一个全局变量中,这样它们就可以在启动时加载,并且在启动过程中会发现一些错误并且模板已经在内存中。

这意味着我无法及时更改工作目录,因为问题已经引起恐慌,并出现错误提示我找不到文件(这正是我想要的行为)。

后来,我发现了一个方法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,我都必须担心正确的资源路径)。
  • 使用“魔术”来确定测试是否运行并相应地更改路径。我不想使用它,因为我必须在我的代码中放置这些检查,而且我讨厌有很多“边缘/特殊”情况。

不是以下内容的重复:

【问题讨论】:

  • 查看github.com/jteeuwen/go-bindata 或其他类似选项将您的资源打包到可执行文件中。
  • 在这个可能的副本中查看一些想法:how to reference a relative file from code and tests
  • @superfell 我知道 go-bindata 但这不是我想要的。我不想将数据存储到 go 源文件中。
  • @icza 这个问题与我的非常相似,但问题已经涵盖了他在第一点的回答。我希望有更好的方法

标签: go resources


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-28
    相关资源
    最近更新 更多