go mod简记

在项目根文件下有 go.mod 文件定义 module path 和依赖库的版本,

1、go mod

go module 安装 package 的原則是先拉最新的 release tag,若无tag则拉最新的commit。
1.1、module path

go.mod 的第一行是 module path,一般采用“仓库+module name” 的方式定义。这样我们获取一个 module 的时候,就可以到它的仓库中去查询,或者让 go proxy 到仓库中去查询。

module github.com/kata-containers/kata-containers/src/runtime
如果你的版本已经 >=2.0.0,按照 Go 的规范,你应该加上 major 的后缀,module path 改成下面的方式:

module github.com/kata-containers/kata-containers/src/runtime/v2.5.0
module github.com/kata-containers/kata-containers/src/runtime/2.5.2
而且引用代码的时候,也要加上v2、v3、vx后缀,以便和其它major版本进行区分。好处:一个项目中可以使用依赖库的不同的 major 版本

1.2 go directive

第二行是 go directive。格式是 go 1.xx,它并不是指你当前使用的 Go 版本,而是指名你的代码所需要的 Go 的最低版本。

go 1.14
因为 Go 的标准库在不断迭代,一些新的 API 会陆续被加进来。如果你的代码用到了这些新的 API,你可能需要指明它依赖的 Go 版本。

这一行不是必须的,可以不写。

1.3 require

require段中列出了项目所需要的各个依赖库以及它们的版本,除了正规的v1.3.0这样的版本外,还有一些奇奇怪怪的版本和注释

require (
code.cloudfoundry.org/bytefmt v0.0.0-20211005130812-5bb3c17173e5
github.com/BurntSushi/toml v0.3.1
github.com/blang/semver v3.5.1+incompatible
github.com/blang/semver/v4 v4.0.0

)
1.3.1伪版本号

code.cloudfoundry.org/bytefmt v0.0.0-20211005130812-5bb3c17173e5
这是 go module 为它生成的一个类似符合语义化版本 2.0.0 版本,实际这个库并没有发布这个版本。v0.0.0-20211005130812-5bb3c17173e5

这里的 20211005130812是这次提交的时间,格式是 yyyyMMddhhmmss, 而5bb3c17173e5就是这个版本的 commit id。通过这个字段,就可以确定这个库的特定的版本。

1.3.2 incompatible

有些库后面加了 incompatible 后缀,但是你如果看这些项目,它们只是发布了 v2.2.1 的 tag,并没有+incompatible后缀。

github.com/blang/semver v3.5.1+incompatible
虽然这些库的版 major 版本已经 >=2 了,但是他们的 module path 中依然没有添加 v2、v3 这样的后缀,不符合 Go 的 module 管理规范。

所以 go module 把它们标记为 incompatible 的,虽然可以引用,但是实际它们是不符合规范的。

1.3.3 indirect注释

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
)
当前项目依赖 A,但是 A 的go.mod 遗漏了 B,那么就会在当前项目的 go.mod 中补充 B,加 indirect 注释;

当前项目依赖 A,但是 A 没有 go.mod,同样就会在当前项目的 go.mod 中补充 B,加 indirect 注释;

当前项目依赖 A,A 又依赖 B。当对 A 降级的时候,降级的 A 不再依赖 B,这个时候 B 就标记 indirect 注释。我们可以执行go mod tidy来清理不依赖的 module。

需要注意的是,从 go 1.17 开始,indirect 的 module 将被放在单独 require 块的,这样看起来更加清晰明了。

1.4、 exclude

如果你想在你的项目中跳过某个依赖库的某个版本,你就可以使用这个段。

exclude (
go.etcd.io/etcd/client/v2 v2.305.0-rc.0
go.etcd.io/etcd/client/v3 v3.5.0-rc.0
)
这样,Go 在版本选择的时候,就会主动跳过这些版本,比如你使用go get -u …或者go get github.com/xxx/xxx@latest等命令时,会执行version query的动作,这些版本不在考虑的范围之内。

1.5 replace

replace 也是常用的一个手段,用来解决一些错误的依赖库的引用或者调试依赖库。

replace (
github.com/coreos/bbolt => go.etcd.io/bbolt v1.3.3
github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.2
github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.3
github.com/uber-go/atomic => go.uber.org/atomic v1.5.1
google.golang.org/genproto => google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8
)
比如 错误使用了github.com/coreos/bbolt作为 bbolt 的 module path,其实这个库在它自己的go.mod 中声明的 module path 是 go.etcd.io/bbolt。

image.png

2、go sum

还有一个 go.sum 的文件,该文件包含特定依赖包的版本内容的散列哈希值,go.sum 记录了所有依赖的 module 的校验信息,以防下载的依赖被恶意篡改,主要用于安全校验。格式如下:


/go.mod
其中 module 是依赖的路径。

version 是依赖的版本号。如果 version 后面跟/go.mod表示对哈希值是 module 的 go.mod 文件;否则,哈希值是 module 的.zip文件。

hash 是以h1:开头的字符串,表示生成 checksum 的算法是第一版的 HASH 算法(SHA256)。如果将来在 SHA-256 中发现漏洞,将添加对另一种算法的支持,可能会命名为 h2。

例如:

github.com/containerd/containerd v1.6.6 h1:xJNPhbrmz8xAMDNoVjHy9YHtWwEQNS+CDkcIRh7t8Y0=
github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0=
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
3、go vendor

go vendor 是go 1.5 官方引入管理包依赖的方式,

基本思路: 将引用的外部包的源代码放在当前工程的vendor目录下面,go 1.6以后编译go代码会优先从vendor目录先寻找依赖包;找不到再从GOPATH 中寻找。

go mod vendor 会将依赖包放到 vendor 目录

image.png

4、go mod命令使用

go mod [arguments]

go mod
The commands are:
download download modules to local cache (下载依赖的module到本地cache))
edit edit go.mod from tools or scripts (编辑go.mod文件)
graph print module requirement graph (打印模块依赖图))
init initialize new module in current directory (再当前文件夹下初始化一个新的module, 创建go.mod文件))
tidy add missing and remove unused modules (增加丢失的module,去掉未用的module)
vendor make vendored copy of dependencies (将依赖复制到vendor下)
verify verify dependencies have expected content (校验依赖)
why explain why packages or modules are needed (解释为什么需要依赖)
1)初始化模块。

在当前目录中初始化新模块,模块名为你项目名。一般是在首次创建项目时使用,将生成go.mod文件。

go mod init [module-path]
复制
(2)添加依赖。

通过 go get 命令可以添加依赖:将依赖项添加到 go.mod 文件,并将依赖项的版本信息记录在 go.sum 文件中。

go get [package-path]
复制
(3)下载依赖的模块到本地 cache。

下载所有依赖的模块

go mod download [all]# 下载指定名称的模块
go mod download PATH@VERSION
复制
edit

-dropexclude=path@version:删除给定模块路径和版本的排除项。

-dropreplace=old[@v]:删除给定模块路径和版本的替代。如果@v省略,删除该模块不带版本的替代。

-droprequire=path:删除给定的模块路径依赖要求的模块。该标志主要提供给工具用以理解模块图。用户应该使用“go get path@none”,可令其它go.mod根据需要调整来满足其它模块施加的限制。

-exclude=path@version:添加给定模块路径和版本的排除项。注意如果排除项已经存在-exclude=path@version是无操作的。

-fmt:重新格式化go.mod文件,不作其他改变。使用或重写go.mod文件的任何其他修改也意味着这种重新格式化。需要该标志的唯一情形是没有指定其它标志,如“go mod edit -fmt”。

-go=version:设置期望的Go语言版本。

-json:以JSON格式打印最终的go.mod,而不是将其写回go.mod。

-module:修改模块路径(go.mod文件的模块行)。

-print:以其文本格式打印最终的go.mod,而不是将其写回go.mod。

-replace=old[@v]=new[@v]:添加给定模块路径和版本对的替代。如果old@v中的@v省略,则左侧不带版本的替代将被添加,应用于old模块路径的所有版本。如果new@v中的@v省略,新路径应为本地模块根目录,而不是模块路径。注意-replace覆盖old[@v]任何冗余的替代,因此省略@v将删除对特定版本的现有替代。

-require=path@version:添加给定的模块路径和版本依赖要求的模块。注意-require覆盖该路径任何已存在的依赖要求的模块。该标志主要提供给工具用以理解模块图。用户应该使用“go get path@version”,其可令其它go.mod根据需要调整来满足其它模块施加的限制。

-require、-droprequire、-exclude、-dropexclude、-replace、-dropreplace标志可以重复,根据给定的顺序应用修改。

注意这只描述go.mod文件自身,不描述其他间接引用的模块。对于构建可使用的的模块的完整集合,使用“go list -m -json all”。

例如,工具可以通过解析“go mod edit -json”的输出以数据结构体的方式获取go.mod,然后可通过使用-require、-exclude等调用“go mod edit”来作出修改,等等。

(4)添加缺少的模块并删除未使用的模块,一般用来更新 go.mod 和 go.sum 文件。

go mod tidy
复制
(5)查看依赖。

通过 go list 命令可以查看项目的依赖,其中 -m 选项表示列出模块而不是包。

go list -m all
复制
(6)查看可升级的依赖。

go list 的 -u 选项将在依赖的模块后面通过中括号显示可用的最新版本(如果有的话)。

go list -m -u all

my/main/module
golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text
rsc.io/pdf v0.1.1 (retracted) [v0.1.2]
复制
(7)升级依赖。

使用 go get 的 -u 选项, 可以将指定依赖升级到最新的次版本号(minor)或修订号(patch)。

go get -u [package-path]
复制
(8)清理模块缓存。

清理模块缓存表示删除存储在本地已下载的模块文件。模块缓存文件存放在 GOPATH/pkg/mod 目录。

go clean -modcache
复制
该命令将会删除 GOPATH/pkg/mod 目录。

可以使用命令 go list -m -u all 来检查可以升级的package,使用go get -u need-upgrade-package 升级后会将新的依赖版本更新到go.mod * 也可以使用 go get -u 升级所有依赖

5、go mod发布和使用

参考Roberto Selbach写的go mod入门文章,文末,我给出链接

Creating a Module

如果你设置好go mod了,那你就可以在任何目录下随便创建

$mkdir gomodone
$cd gomodone
在这个目录下创建一个文件say.go

package gomodone

import “fmt”

// say Hi to someone
func SayHi(name string) string {
return fmt.Sprintf(“Hi, %s”, name)
}
初始化一个 go.mod文件

$ go mod init github.com/jacksonyoudi/gomodone
go: creating new go.mod: module github.com/jacksonyoudi/gomodone
查看 go.mod内容如下:

github.com/jacksonyoudi/gomodone
go 1.14
下面我们要将这个module发布到github上,然后在另外一个程序使用

$git init
$vim .gitiiignore
$git commit -am “init”
// github创建对应的repo
$git remote add origin git@github.com:jacksonyoudi/gomodone.git
$git push -u origin master
执行完,上面我们就相当于发布完了。

如果有人需要使用,就可以使用

go get github.com/jacksonyoudi/gomodone
这个时候没有加tag,所以,没有版本的控制。默认是v0.0.0后面接上时间和commitid。如下:

gomodone@v0.0.0-20200517004046-ee882713fd1e
官方不建议这样做,没有进行版本控制管理。

module versioning

使用tag,进行版本控制

making a release

git tag v1.0.0
git push --tags
操作完,我们的module就发布了一个v1.0.0的版本了。

推荐在这个状态下,再切出一个分支,用于后续v1.0.0的修复推送,不要直接在master分支修复

$git checkout -b v1
$git push -u origin v1

go mod edit -require github.com/containerd/containerd@v1.4.3

go mod tidy

go mod vendor

  • 18
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值