如何获取 Go 模块依赖项的路径?

时间:2021-04-22 10:56:42

标签: go code-generation go-modules

我有两个 Go 模块,让我们将它们命名为 example.com/aexample.com/b

让它成为example.com/a的{​​{1}}:

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 字符不是导入路径的一部分。我希望有一些 !go mod 的子命令可以输出路径,但我没有在文档中找到它。

我曾考虑通过 go list 在 Go 代码中包含 data.yaml(是的,我知道 go-bindata 但我现在不想要求 Go 1.16)但后来我只有在编译时需要时才能在运行时访问。

2 个答案:

答案 0 :(得分:2)

您可以将 go list-m 标志和 -f 标志一起使用,如下所示:

go list -m -f '{{.Dir}}' example.com/b

-m 标志:

<块引用>

导致 go list 列出模块而不是包。在这种模式下, go list 的参数可能是模块、模块模式(包含 ...通配符)、版本查询或特殊模式 all,其中 匹配构建列表中的所有模块。如果没有指定参数, 列出了主模块。

(reference)

-f 标志:

<块引用>

指定输出的替代格式,使用的语法为 包模板。传递给模板的结构,使用时 -m 标志是:

type Module struct {
    Path      string       // module path
    Version   string       // module version
    Versions  []string     // available module versions (with -versions)
    Replace   *Module      // replaced by this module
    Time      *time.Time   // time version was created
    Update    *Module      // available update, if any (with -u)
    Main      bool         // is this the main module?
    Indirect  bool         // is this module only an indirect dependency of main module?
    Dir       string       // directory holding files for this module, if any
    GoMod     string       // path to go.mod file for this module, if any
    GoVersion string       // go version used in module
    Error     *ModuleError // error loading module }

type ModuleError struct {
    Err string // the error itself
}

[以上引用因上下文而改变]

(reference)

答案 1 :(得分:2)

你可以这样算出模块路径:

package main

import (
    "fmt"
    "os"
    "path"

    "golang.org/x/mod/module"
)

func GetModulePath(name, version string) (string, error) {
    // first we need GOMODCACHE
    cache, ok := os.LookupEnv("GOMODCACHE")
    if !ok {
        cache = path.Join(os.Getenv("GOPATH"), "pkg", "mod")
    }

    // then we need to escape path
    escapedPath, err := module.EscapePath(name)
    if err != nil {
        return "", err
    }

    // version also
    escapedVersion, err := module.EscapeVersion(version)
    if err != nil {
        return "", err
    }

    return path.Join(cache, escapedPath+"@"+escapedVersion), nil
}

func main() {
    var path, err = GetModulePath("github.com/jakubDoka/mlok", "v0.4.7")
    if err != nil {
        panic(err)
    }

    if _, err := os.Stat(path); os.IsNotExist(err) {
        fmt.Println("you don't have this module/version installed")
    }
    fmt.Println("module found in", path)
}
相关问题