go get机制解读

下篇: go module代理(goproxy)与本地缓存

go get/ go mod tidy 问题汇总



20240818

go get 背后经历了什么

go get 背后经历了什么?

关于 go get 的一个常见误解是认为在 get 后面直接跟上网址就可以下载源码。实际上,这混淆了模块名称和源码仓库的概念。go get 后面跟的本质上是模块名称。

例如,对于 “gorm.io/“ 这个模块:

  1. “gorm” 这个字符串是模块名称。
  2. 要找到它对应的源码地址,我们可以使用 Postman:
    • 在模块名称前加上 “https://“
    • 在后面加上参数 “?go-get=1”
    • 通过 GET 方法请求这个地址
  3. 返回的内容中,在 content 部分会告诉我们对应的源码地址,例如 “github.com/go-gorm/gorm”

因此,go get 背后进行了两个步骤:

  1. 请求上述地址,获取对应的源码仓库地址
  2. 通过 Git clone 下载对应的源码
  3. 将下载的源码放到本地的 GOPATH/pkg/mod 目录下

在本地的 GOPATH/pkg/mod 目录中:

  1. 大部分第三方库都放在 “github.com” 这个目录下
  2. 但 “gorm.io” 对应的是 “gorm.io” 这个目录
  3. 文件系统中的目录名称对应的是模块名称,而不是源码的仓库地址

注意:

  • 如果模块名称包含大写英文字母,在文件系统中会转成小写,并在前面加一个感叹号(!)
  • 例如,大写的 P 和 B 在目录名中会变成 “!p” 和 “!b”

如果只想下载项目中的某个子目录:

  • 例如,只想下载 gorm 的 logo 目录
  • 可以在 go get 后面加上 “/logo”

指定版本下载:

  1. 在源码仓库中,可以看到多个历史版本
  2. go get 可以指定具体版本,例如:
    go get gorm.io/gorm@v1.25.7
  3. 不显式指定版本号时,默认使用最高版本号
  4. 上述操作实际上是从 v1.25.10 降级到 v1.25.7

关于主版本号:

  1. 如果主版本号不是 0 或 1,必须在模块名称中指定主版本号
  2. 例如,对于 etcd 使用 v3 主版本号,必须指定 v3
  3. 如果只需下载 API 这个子目录,可以这样写:
    go get go.etcd.io/etcd/api/v3
  4. 即使对于 v3 这个主版本号,也有多个次版本号,可以指定具体版本:
    go get go.etcd.io/etcd/api/v3@v3.5.14

文章目录