【发布时间】:2021-07-16 14:16:10
【问题描述】:
我有两个 Go 模块,我们将它们命名为 example.com/a 和 example.com/b。
假设这是example.com/a的go.mod:
module example.com/a
go 1.12
require (
example.com/b v0.4.2
)
在example.com/b的根目录下,有一个名为data.yaml的文件。 example.com/a 需要在构建过程中自动生成一些代码。这个自动生成需要读取data.yaml。
如何在example.com/a的目录下查询example.com/b的路径来读取那个文件?我知道下载后,模块将位于(go env GOPATH)/pkg/mod 中的somewhere,但我不知道如何从那里构造路径,因为它包含一些不属于导入路径。我希望有一些go mod或go list的子命令会输出路径,但我在文档中没有找到。
我曾考虑通过go-bindata 将data.yaml 包含在Go 代码中(是的,我知道//go:embed,但我现在不想要求Go 1.16)但是我只能在运行时访问-我在编译时需要它的时间。
【问题讨论】:
-
不确定您是否考虑过此选项,但是您可以让
example.com/b导出一个函数,该函数使用runtime.Caller来确定其文件的位置,并使用该函数构造 yaml 文件的绝对路径并返回它。然后example.com/a可以调用此函数来获取该位置。我自己确实使用这种方法,其中a导入b,a调用b的函数,该函数从其自己模块的文件夹层次结构中读取css/js/html 文件,然后将这些文件的副本写入@ 987654347@. -
@mkopriva 有趣的想法,但仍然是运行时解决方案。代码生成器在我编译并链接到
example.com/b之前运行,所以我不能从那里调用函数。 -
“但我不知道如何从那里构造路径,因为它包含一些不属于导入路径的 ! 字符。” -- 请参阅表格正上方的段落here:“为避免在从不区分大小写的文件系统中提供服务时出现歧义,$module 和 $version 元素通过将每个大写字母替换为感叹号后跟相应的小写字母进行大小写编码-case letter。这允许模块 example.com/M 和 example.com/m 都存储在磁盘上,因为前者被编码为 example.com/!m。"
-
在我的系统上将包
github.com/BurntSushi/toml目录位置转换为/Users/mkopriva/Work/go/pkg/mod/github.com/!burnt!sushi/toml@v0.3.1-- 所以也许你可以使用该规则来确保在正确的位置找到包。 -
另外,如果你的生成器是用 Go 编写的,并且你可以为此目的修改它,你可以使用包 golang.org/x/tools/go/packages 来加载一个包带有
packages.NeedModule标志,它将在包的模块上加载信息,包括它的目录,如果有的话。
标签: go code-generation go-modules