1. 用法:go mod <command> [arguments]
  2. command支持命令列表:
命令 go mod <command> 作用
go mod init 生成 go.mod 文件
go mod download 下载 go.mod 文件中指明的所有依赖
go mod tidy 整理现有的依赖
go mod graph 查看现有的依赖结构
go mod edit 编辑 go.mod 文件
go mod vendor 导出项目所有的依赖到vendor目录
go mod verify 校验一个模块是否被篡改过
go mod why 查看为什么需要依赖某模块

go mod init

  1. 用法:go mod init [module-path]
  2. 示例:
# 初始化当前目录并创建一个go.mod文件,模块路径根据其他条件推断判断
$ go mod init

# 初始化当前目录并创建一个go.mod文件,模块路径为example.com/m
$ go mod init example.com/m
  1. 介绍:
    • go mod init命令在当前目录中初始化并写入一个新的go.mod文件,实际上创建了一个以当前目录为根的新模块。
    • go.mod文件必须不存在时执行上面命令,否则会提示go.mod文件已存在提示。
    • 如当前存在一个空项目demo,在demo目录下执行go mod init gitee.com/bms/demo,会生成如下go.mod文件,当前go版本是go1.16.3
module gitee.com/bms/demo

go 1.16
  1. init接受一个可选参数,即新模块的模块路径,有关选择模块路径的说明,请参阅模块路径。
  2. 如果省略了模块路径参数,init将尝试使用.go文件、vendoring工具配置文件和当前目录(如果在GOPATH中)中的导入注释来推断模块路径。
  3. 如果存在vendoring工具的配置文件,init将尝试从中导入模块需求。
  4. init支持以下配置文件:
    • GLOCKFILE (Glock)
    • Godeps/Godeps.json (Godeps)
    • Gopkg.lock (dep)
    • dependencies.tsv (godeps)
    • glide.lock (glide)
    • vendor.conf (trash)
    • vendor.yml (govend)
    • vendor/manifest (gvt)
    • vendor/vendor.json (govendor)
  5. Vendoring工具配置文件无法始终以完美的保真度进行翻译。
    • 例如,同一个仓库中的多个包在不同版本中导入,而仓库中只包含一个模块,那么导入的go.mod就只能需要一个版本的模块。
    • 您可能希望运行go list -m all以检查构建列表中的所有版本,并运行go mod tidy以添加缺少的需求并删除未使用的需求。

go mod download

  1. 将命名的模块下载到模块缓存中(模块缓存参考官方模块参考文档)。
  2. 参数可以是模块路径或模块模式,选择主模块的依赖项或表单的版本查询path@version
  3. 不带参数,download适用于主模块的所有依赖项。
  4. go命令将在正常执行期间根据需要自动下载模块。
  5. go mod download命令主要用于预填充模块缓存或加载要由模块代理服务的数据。
  6. 默认情况下,download不向标准输出写入任何内容。它将进度消息和错误打印到标准错误。

用法:go mod download [-json] [-x] [modules]
  1. -json
    • -jsondownload将一系列JSON对象打印到标准输出,描述每个下载的模块(或失败)
    • 对应如下结构:
type Module struct {
    Path     string // 模块路径
    Version  string // 模块版本
    Error    string // 错误模板描述
    Info     string // 缓存的 .info 文件的绝对路径
    GoMod    string // 缓存 .mod 文件的绝对路径
    Zip      string // 缓存的 .zip 文件的绝对路径
    Dir      string // 缓存源根目录的绝对路径
    Sum      string // checksum路径,版本(比如在go.sum)
    GoModSum string // go.mod的checksum(比如在go.sum)
  1. -xdownload打印命令download执行到标准错误

  1. 示例:
$ go mod download -json -x gitee.com/phpbms/demo
{
    "Path": "gitee.com/phpbms/demo",
    "Version": "v0.0.0-20211021090521-71a745ffbccb",
    "Info": "/mnt/g/Go/worker/pkg/mod/cache/download/gitee.com/phpbms/demo/@v/v0.0.0-20211021090521-71a745ffbccb.info",
    "GoMod": "/mnt/g/Go/worker/pkg/mod/cache/download/gitee.com/phpbms/demo/@v/v0.0.0-20211021090521-71a745ffbccb.mod",
    "Zip": "/mnt/g/Go/worker/pkg/mod/cache/download/gitee.com/phpbms/demo/@v/v0.0.0-20211021090521-71a745ffbccb.zip",
    "Dir": "/mnt/g/Go/worker/pkg/mod/gitee.com/phpbms/demo@v0.0.0-20211021090521-71a745ffbccb",
    "Sum": "h1:JJlXgKY8MUQtOlnSHtbIsHtRU9DNbxx9NUgpsDt3pQA=",
    "GoModSum": "h1:6H8vzSoXg8Ey2gdfFaP7ToLmbOnfc04IAcuTFDKqSV8="
}

go mod tidy

  1. go mod tidy确保go.mod文件与模块中的源代码匹配。
    • 它添加了构建当前模块的包和依赖项所需的任何缺失的模块要求,并删除了对不提供任何相关包的模块的要求。
    • 它还向go.sum添加任何缺失的条目并删除不必要的条目。
  2. go mod tidy通过递归加载主模块中的所有包以及它们导入的所有包来工作,这包括测试导入的包(包括其他模块中的测试)。
  3. go mod tidy就像启用了所有构建标记一样,因此它会考虑特定于平台的源文件和需要自定义构建标记的文件,即使这些源文件通常不会被构建。
  4. 有一个例外:忽略构建标记未启用,因此不会考虑具有构建约束【// +build ignore】的文件。
  5. 请注意,go mod tidy不会考虑主模块中名为testdata或名称以._除非这些包是由其他包显式导入的。
  6. 一旦go mod tidy加载了这组包,它会确保提供一个或多个包的每个模块在主模块的go.mod文件中都有一个require指令,或者如果主模块在go 1.16或更低版本 - 是必需的另一个必需的模块。
  7. go mod tidy将添加对每个缺失模块的最新版本的要求(有关最新版本的定义,请参阅版本查询),go mod tidy将删除不提供上述集合中任何包的模块的require指令。
  8. go mod tidy还可以添加或删除require 指令的// indirect// indirect间接注释表示模块不提供由主模块中的包导入的包。
  9. 用法:go mod tidy [-e] [-v] [-go=version] [-compat=version]
  10. 介绍:
    • -e:(在Go 1.16中添加)在加载包时遇到错误时尝试继续。
    • -v:将有关已删除模块的信息打印到标准错误。
    • -go=:将go指令更新为指定的版本,根据该版本启用或禁用模块图修剪和延迟模块加载(并根据需要添加或删除// indirect间接注释)。
    • -compat=:当模块图由go指令中指示的版本之前的Go版本加载时,go mod tidy将检查所选版本的模块是否不会更改。还可以通过-compat标志显式指定版本检查的兼容性。

go mod graph

  1. 以文本形式打印模块需求图
  2. 用法:go mod graph [-go=version]
  3. 介绍:
    1. 模块图中的每个顶点代表一个模块的特定版本,图中的每条边代表对依赖项的最低版本的要求。
    2. go mod graph打印图形的边缘,每行一个。
      • 每行有两个空格分隔的字段:模块版本及其依赖项之一。
      • 每个模块版本都标识为path@version形式的字符串。
      • 主模块没有@version后缀,因为它没有版本。
    3. -go=go mod graph报告给定Go版本加载的模块图,而不是go.mod文件中的go指令指示的版本。
    4. 有关如何选择版本的更多信息,请参阅最小版本选择(MVS)。
      • 另请参阅go list -m以打印选定的版本,并查看go mod why以了解为什么需要模块。
example.com/main example.com/a@v1.1.0
example.com/main example.com/b@v1.2.0
example.com/a@v1.1.0 example.com/b@v1.1.1
example.com/a@v1.1.0 example.com/c@v1.3.0
example.com/b@v1.1.0 example.com/c@v1.1.0
example.com/b@v1.2.0 example.com/c@v1.2.0

go mod edit

  1. 该命令提供了一个用于编辑和格式化go.mod文件的命令行界面,主要供工具和脚本使用。
  2. go mod edit只读取一个go.mod文件,它不查找有关其他模块的信息。
  3. 默认情况下,go mod edit读取和写入go.mod主模块的文件,但可以在编辑标志后指定不同的目标文件。

用法:go mod edit [editing flags] [-fmt|-print|-json] [go.mod]
  • editing flags:指定编辑操作选项:(editing flags可以重复使用,按给定的顺序)
    1. -module:更改模块的路径(go.mod文件的module行),修改module行模块名称。
    2. -go=version:设置go.mod文件的Go版本。
    3. -require=path@version:添加指定的模块路径和版本上的要求,会覆盖go.mod上的任何现有要求path
    4. -droprequire=path:删除指定的模块路径和版本上的要求。
    5. -exclude=path@version:增加给定的模块路径,-exclude=path@version如果该排除已存在, 则为空操作。
    6. -dropexclude=path@version:放弃对给定的模块路径和版本的排除。
    7. -replace=old[@v]=new[@v]:添加了给定模块路径和版本对的替换。
      • 如果省略old@v则添加左侧没有版本的替换,这适用于旧模块路径的所有版本。
      • 如果省略new@v则新路径应该是本地模块根目录,而不是模块路径。
      • 注意:-replace覆盖的任何冗余替换old[@v],因此省略@v将删除特定版本的替换。
    8. -dropreplace=old[@v]:丢弃给定模块路径和版本对的替换。
      • 如果@v提供了,则删除给定版本的替换,左侧没有版本的现有替代品仍可更换模块。
      • 如果@v省略 ,则删除没有版本的替换。
    9. -retract=version:添加回收对于给定的版本,其可以是一个单一的版本(如v1.2.3)或间隔(等[v1.1.0,v1.2.0])。
      • 注意:-retract标志不能为retract指令添加基本原理注释。
    10. -dropretract=version:删除回收对于给定的版本。
  • -fmt、-print、-json:额外标志来控制输出。
    1. -fmt:重新格式化go.mod文件而不进行其他更改。
      • 使用或重写go.mod文件的任何其他修改也暗示了这种重新格式化。
      • 唯一需要此标志的情况是没有指定其他标志,如go mod edit -fmt
    2. -printgo.mod以其文本格式打印final ,而不是将其写回磁盘(就是打印go.mod文件内容)。
    3. -jsongo.mod以 JSON 格式打印最终结果,而不是以文本格式将其写回磁盘go mod edit -json
// json打印格式
{
  "Module": {
      "Path": "mymod"
  },
  "Go": "1.17",
  "Require": [
      {
          "Path": "gitee.com/phpbms/demo",
          "Version": "v0.0.0-20211021090521-71a745ffbccb",
          "Indirect": true
      }
  ],
  "Exclude": null,
  "Replace": null,
  "Retract": null
}
// 对应相关结构体
type Module struct {
  Path    string
  Version string
}

type GoMod struct {
  Module  Module
  Go      string
  Require []Require
  Exclude []Module
  Replace []Replace
}

type Require struct {
  Path     string
  Version  string
  Indirect bool
}

type Replace struct {
  Old Module
  New Module
}

type Retract struct {
  Low       string
  High      string
  Rationale string
}

  1. 示例:
# 添加替换指令
$ go mod edit -replace example.com/a@v1.0.0=./a

# 删除替换指令
$ go mod edit -dropreplace example.com/a@v1.0.0

# 设置go版本,添加需求,打印文件而不是写入磁盘
$ go mod edit -go=1.14 -require=example.com/m@v1.0.0 -print

# 格式化 go.mod 文件
$ go mod edit -fmt

# 格式化并打印不同的 .mod 文件
$ go mod edit -print tools.mod

# 打印 go.mod 文件的 JSON 表示
$ go mod edit -json

# 所有命令使用
$ go mod edit -module=mydemo1 -go=1.16 -require=gitee.com/phpbms/demo/v3@v3.0.0 -exclude=gitee.com/phpbms/demo/v3@v3.0.1 -replace=gitee.com/phpbms/demo/v2@v2.0.1=gitee.com/phpbms/demo/v2@v2.0.0 -retract=v1.1.1 -print ./go.mod

# 修改go版本,从之前的 go 1.20 修改为 go 1.21rc2
$ go mod edit -go 1.21rc2

go mod vendor

  1. 在主模块的根目录中构造一个名为vendor的目录,该目录包含支持主模块中包的构建和测试所需的所有包的副本
    • 不包括仅通过主模块之外的包测试导入的包。
    • go mod tidy和其他模块命令一样,在构建vendor目录时不考虑除了ignore之外的构建约束。
  2. 当启用vendoring时,go命令将从vendor目录加载包,而不是将模块从其源下载到模块缓存中,并使用那些下载副本的包。
  3. go mod vendor还会创建文件vendor/modules.txt,其中包含vendor包的列表以及从中复制它们的模块版本。
    • 当启用vendoring时,此清单用作模块版本信息的来源,如go list -mgo version -m所报告的。
    • go命令读取vendor/modules.txt时,它会检查模块版本是否与go.mod一致。
    • 如果go.modvendor/modules.txt生成后发生了变化,则应再次运行go mod vendor
  4. 请注意,go mod vendor会在重新构建之前删除vendor目录(如果它存在)。
    • 不应对vendor的软件包进行本地更改。
    • go命令不会检查vendor目录中的包是否未被修改,但是可以通过运行go mod vendor并检查没有进行任何更改来验证vendor目录的完整性。
  5. 使用:go mod vendor [-e] [-v]
    • -e:(在Go 1.16中添加)在加载包时遇到错误时尝试继续。
    • -v:将vendor模块和包的名称打印为标准错误。

go mod verify

  1. 检查存储在模块缓存中的主模块的依赖项自下载以来没有被修改
  2. 执行此检查,对每个下载的module.zip文件和提取的目录进行散列然后将这些散列与首次下载模块时记录的散列进行比较。
  3. go mod verify 检查构建列表中的每个模块(可以使用go list -m all打印所有模块)。
  4. 如果所有模块都未修改,则go mod verify 打印all modules verified否则,它将报告哪些模块已更改并以非零状态退出。
  5. 注意:所有模块感知命令都会验证主模块的go.sum文件中的哈希值是否与为下载到模块缓存中的模块记录的哈希值匹配。
  6. 如果go.sum中缺少哈希(例如,因为模块是第一次使用),则go命令使用校验和数据库验证其哈希。
    • 除非模块路径与GOPRIVATEGONOSUMDB匹配。
  7. go mod verify不会为不在缓存中的模块下载内容,也不会使用go.sum文件来验证模块内容。
  8. 但是,go mod verify可能会下载go.mod文件以执行最少的版本选择。
  9. 它将使用go.sum来验证这些文件,并且可能会为丢失的哈希添加go.sum条目。
  10. 用法:go mod verify
$ go mod verify
all modules verified

go mod why

  1. go mod why在导入图中显示从主模块到每个列出的包的最短路径。
  2. 用法:go mod why [-m] [-vendor] packages...
    • -mgo mod why将其参数视为模块列表。
      • go mod why会打印每个模块中任何包的路径。
      • 请注意,即使使用-mgo mod why查询包图,而不是go mod graph打印的模块图。
    • -vendorgo mod why忽略主模块之外的包测试中的导入(就像go mod vendor所做的那样)。
      • 默认情况下, go mod why会考虑与all模式匹配的包图。
      • 这个标志在Go 1.16之后在声明go 1.16或更高版本的模块中无效(使用go.mod中的go指令),因为all的含义已更改以匹配go mod供应商匹配的包集。
  3. 示例:
    • 输出是一个节序列,每个在命令行上命名的包或模块都有一个节,用空行分隔。
    • 每节以注释行开头,以#开头,给出目标包或模块。
    • 后续行给出了通过导入图的路径,每行一个包。
    • 如果包或模块不是从主模块引用的,则该节将显示一个带括号的注释,表明该事实。
$ go mod why golang.org/x/text/language golang.org/x/text/encoding
# golang.org/x/text/language
rsc.io/quote
rsc.io/sampler
golang.org/x/text/language

# golang.org/x/text/encoding
(main module does not need package golang.org/x/text/encoding)