如何将 Go 虚荣导入 URL 设置为 monorepo 中的存储库子目录?

How to set Go vanity import URL to repository subdirectory in a monorepo?

我正在使用按顶级语言组织的 monorepo,因此所有 Go 模块都位于存储库根目录中的 go 目录中。我想设置一个虚导入 URL 指向 go 目录而不是存储库根目录,这样 go/ 就不需要包含在导入路径中。

当前文件结构:

/
  go/
    module1/
    module2/

所需的导入格式:

import (
    "go.example.com/module1"
    "go.example.com/module2"
)

目前可能,但需要:

import (
    "go.example.com/go/module1"
    "go.example.com/go/module2"
)

根据 docsgo.example.com 处的 <meta> 元素的格式应为以下形式:

<meta name="go-import" content="import-prefix vcs repo-root">

所以在这种情况下我会:

<meta name="go-import" content="go.example.com git github.com/example/repo">

这会将 import-prefix 之后的路径转换为相对于存储库根目录的路径,以便 go.example.com/this/path 在存储库中查找 this/path 目录。我希望路径相对于回购中的 go 目录而不是回购根目录。

有什么方法可以通知 go get go.example.com 之后的路径应该是相对于 github.com/example/repo/go 而不仅仅是 github.com/example/repo 的?

不是直接的,但有解决方法。

来自 this issue in golang/go:

[...] there is currently no way for the HTTPS server to indicate that the module is offset by the prefix src/go, since that is not a part of the Go package path. This layout is just not going to work with the go command's built-in git support.

go 命令的 built-in git 支持下,导入规范以存储库的 URL 开头,然后是所需包的路径。因此路径必须相对于存储库根目录。使用个性化导入路径,如果需要,您可以使路径 更长 ,但不能更短(例如 example.com/pkg)。

因此以下是没有解决方法的最短导入路径:go.example.com/go/<module>.


解决方法

对于真正敬业的人。

这些涉及一些设置和额外的处理,可能不值得仅仅为了导入路径的美观。

我已经研究出两种方法(还有一种 semi-solution 可能不适用于大量模块)。首先是设置模块代理。第二个是创建另一个从 go 目录复制并从那里导入的 repo。

go.mod

中使用replace

这个非常简单,您可以根据自己的喜好设置基本导入路径,只需 replace 它在 go.mod 文件中即可。

缺点是管理许多相互依赖的模块变得很复杂(如下一节的链接文章中所述)。也感觉不那么特别,负担在 importing 项目而不是 imported 项目。

转到模块代理

This article(gist) 很好地解释了这种方法。

go get 使用 GOPROXY 环境变量来决定在哪里查找和解析包。基本思想是设置一个知道如何翻译 public 模块名称并从实际 repo 获取相关代码的代理服务器,然后将该服务器的 URL 放入 GOPROXY变量。

对于私有 modules/repositories 这种方法需要格外小心,因为您还必须处理身份验证。

复制Git存储库

最后一种方法是将 go 目录的内容复制到另一个存储库,这可以通过 GitHub Actions 或类似工具自动完成。

要保留版本标签(如果使用)和分支(尽管不提交哈希),您可以使用 git filter-repo 重写历史,以便 go 目录实际上是包根目录(并且始终已经):git filter-repo --subdirectory-filter go/.

然后只需将虚荣 go-import 标签设置为:

<meta name="go-import" content="go.example.com git github.com/example/repo-go">

(原始回购是 github.com/example/repo)。