Kubernetes 的仓库在 github.com/kubernetes/kubernetes, 按照默认的习俗来说, 项目对应 Go Module 应该是 github.com/kubernetes/kubernetes. 但熟悉的同学都知道, kubernetes 的 module 是 k8s.io/kubernetes.

这依赖 https://k8s.io/kubernetes?go-get=1 在返回中包括特定的标签 <meta name="go-import".

 ~ curl https://k8s.io/kubernetes\?go-get\=1

            <html><head>
                  <meta name="go-import"
                        content="k8s.io/kubernetes
                                 git https://github.com/kubernetes/kubernetes">
                  <meta name="go-source"
                        content="k8s.io/kubernetes
                                 https://github.com/kubernetes/kubernetes
                                 https://github.com/kubernetes/kubernetes/tree/master{/dir}
                                 https://github.com/kubernetes/kubernetes/blob/master{/dir}/{file}#L{line}">
            </head></html>

Go Module 支持识别 content 中的内容, 以 git 协议去 https://github.com/kubernetes/kubernetes 获取对应内容.

官方对此的介绍位于 Serving modules directly from a proxy.

在公司使用内部部署的 git 服务时, 我经常使用上述的逻辑去优化 Go 的体验:

  • 使用简短有象征意义的域名代替繁琐的代码仓库的域名
  • 直接指定 SSH 地址, 避免每个 Go 开发都需要处理私仓的访问

返回的内容类似:

<html><head>
    <meta name="go-import"
        content="ohai.bot/zeus git ssh://git@dev.companion.host:30022/group/zeus">
</head></html>

再不使用 go-import 标签的情况下, Go 访问 Git 私有仓库一般通过 git 配置来将 https 替换为 ssh.

git config --global url."ssh://git@dev.companion/".insteadOf "https://dev.companion/"

总的而言, 当我们在 Go 中处理某个依赖时:

  • 对于众所周知的地址, Go 会直接按特定的逻辑处理. 如 github.com 开头的地址都会通过 git 去获取对应内容.
  • 或者, 则尝试获取 go-import 标签后再处理
  • 否则, 按 git 协议尝试