大致梳理这几部分:更新历程,大致规则,命令解释,实践操作
Mod展示
- ➜ ~ go mod
- Go mod provides access to operations on modules.
- Note that support for modules is built into all the go commands,
- not just 'go mod'. For example, day-to-day adding, removing, upgrading,
- and downgrading of dependencies should be done using 'go get'.
- See 'go help modules' for an overview of module functionality.
- Usage:
- go mod
[arguments] - The commands are:
- download download modules to local cache
- edit edit go.mod from tools or scripts
- graph print module requirement graph
- init initialize new module in current directory
- tidy add missing and remove unused modules
- vendor make vendored copy of dependencies
- verify verify dependencies have expected content
- why explain why packages or modules are needed
- Use "go help mod
" for more information about a command.
Mod历程
时间线:
event: Go 1.12发布 Modules 默认为 auto;
2019
event: Go 1.11发布 Modules 作为官方试验;
2018
event: Go 1.7: vendor 目录永远启用2017年1月 Go 团队发布 Dep,作为准官方试验;
2016
event: Go 1.6 vendor 机制 默认开启2016年5月 Go 团队的 Peter Bourgon 建立委员会,讨论依赖管理工具,即dep;
2016
event: Go 1.5 实验性质加入 vendor 机制2015年 有人提出了采用语义化版本的草案;
2015
event: Go 1.5之前的各种草案;
- 2015年 govendor,kardianos/govendor;
- 2015年 gb;
- 2014年 有人提出 external packages 的概念,在项目的目录下增加一个 vendor 目录来存放外部的包;
- 2014年 glide
- 2014年 gopkg.in;
- 2013年10月 Godep
- 2012年 goven,github/kr/goven;
- 2012年 Go发布,只有GOPATH
2015
Mod规则
module是发布、版本控制和分发的集合,可以直接从版本控制存储库或模块代理服务器下载包。 go module 主要使用语义化版本、导入兼容性规则、最小版本选择。
语义化版本
版本格式:主版本号.次版本号.修订号,版本号 递增规则如下: 主版本号:当你做了不兼容的 API 修改, 次版本号:当你做了向下兼容的功能性新增, 修订号:当你做了向下兼容的问题修正。 先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。
导入兼容性规则
如果新包和旧包具有相同的导入路径,则新包必须向后兼容旧包。
最小版本选择(MVS)
介绍
最小版本选择的关键是偏好选择模块允许的最小版本。
例如
递归构建列表。
最终根据最小版本选择找到每个module的最大版本,那就是满足需求的最小版本。
Go Module 使用Russ Cox提出的最小版本选择算法选择构建包。
主要包括四个操作:
- 构建当前的构建列表。
- 将所有模块升级到最新版本。
- 将一个模块升级到特定的较新版本。
- 将一个模块降级到特定的旧版本。
构建
替换
replace C v1.4 => R
排除
exclude C v1.3
升级
升级B v1.2到B v1.3
要保留升级,Go命令将更新Go.mod中的require,它将将B的要求更改为1.3版。它还将在// indirect 注释中添加C 1.4和D 1.3的要求,否则这些版本不会被选择。
降级
C v1.4降级
Mod文件
格式
- ➜ ~ cat go.mod
- #module 指令指定路径,go.mod 必须包含一个module指令
- module example.com/my/thing
- #go 指令后面跟版本号,必须是有效的版本号;go1.17之后,如果没有设置,则默认go1.16
- go 1.17
- #require 指令声明依赖库的最低版本,加载require指令后,go按照MSV生成构建列表。
- require example.com/other/thing v1.0.2
- require example.com/new/thing/v2 v2.3.4
- #exclude 指令可以防止对应版本的加载。
- exclude example.com/old/thing v1.2.3
- #replace 指令替换代码库某一版本、或者所有版本,新模块可以为另一模块路径版本或者对应系统的文件目录。
- replace example.com/bad/thing v1.4.5 => example.com/good/thing v1.4.5
- #retract 指令撤回版本,例如某个第三方库的某一版本有误,可以添加到此处。
- retract [v1.9.0, v1.9.5]
命令
模块感知命令
GO111MODULE
- on或者未设置: 启用module模式,即使go.mod不存在
- off: 禁用module模式,使用GOPATH模式
- auto: go.mod存在或者任意的父目录存在,启用module模式
使用go env命令查看,可以使用go env -w GO111MODULE=on修改。
常用命令
go get
用法:
go get [-d] [-t] [-u] [build flags] [packages]
例子:
#升级特定模块。
$ go get -d golang.org/net
#升级模块,提供主模块中的包导入的包。
$ go get -d -u / ...
#升级或降级到模块的特定版本。
$ go get -d golang.org/x/text@v0.3.2
#更新到模块的主分支机构上的提交。
$ go get -d golang.org/x/text@master
#删除对需要它的模块和降级模块的依赖项
#到不需要它的版本。
$ go get -d golang.org/x/text@none
go list
go list -m
用法:
go list -m [-u] [-retracted] [-versions] [list flags] [modules]
例子:
$ go list -m all
$ go list -m -versions example.com/m
$ go list -m -json example.com/m@latest
go mod graph
打印package
引用关系
例如:
- ➜ crypto-data-etl git:(master) ✗ go list -m all
- crypto-data-etl
- bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898
- 看到bazil包,想要看是谁使用了,就可以使用该命令
- ➜ crypto-data-etl git:(master) ✗ go mod graph | grep bazil
- github.com/containerd/continuity@v0.0.0-20191214063359-1097c8bae83b bazil.org/fuse@v0.0.0-20160811212531-371fbbdaa898
goproxy
go env -w GOPROXY=https://goproxy.cn,direct
这个命令可以说是需要经常使用
Mod实践
回顾
初始化
go mod init [folder]
下载
go get package_link@version
更新
go mod tidy
指定版本
go mod edit -replace=package_link@old_version=package_link@new_version
更新到vendor
go mod vendor
实践
前辈蜜汁操作
比如前辈自己拷贝的库,tag对应代码不对,需要针对某个commit id
拉取代码;
go mod edit -require github.com/windless0530/redis-go-cluster@f6b361520b1277d838c4e44efe8628caddc9900b
如图:
过时不过气包
比较老旧的包,定位当前使用版本,要注意找到包的tag名称。由于不能升级,所以需要定位到特定tag。
go mod edit -replace github.com/apache/thrift=git.apache.org/thrift.git@0.9.3.1
如图:
开发者不坑人
开发者改了github
的username
,比如这位logrus开发者。
go mod edit -replace github.com/Sirupsen/logrus=github.com/sirupsen/logrus@v1.6.0
如图:
本地的公共包
go mod edit -replace=go-base=../go-base
此处有个问题,就是在自己本地的相对路径,其他同事并不可通用,此时需要另一个命令,go.work go的工作区模式,将replace本地目录,移到本地的工作区中。