Golang Modules

魔幻涂鸦

前言


mod 是 modules 的简称,Go 1.11 和 Go 1.12 早已支持 modules。
在 Go 1.11 中 $GOPATH/src 目录下,即使有 go.mod 那也是工作在 GOPATH 模式下;从 Go 1.13 开始默认为 module 模式。

modules 使用 semantic version tags 格式为:major.minor.patch(如:v0.1.2), major 为大版本号,minor 为小版本号,patch 为补丁号。

依赖包后面的 // indirect 注释表明这个包是间接被这个 module 所依赖。

在 module 目录下使用 go get xxx 会使 xxx 依赖包升至最新版本(默认为:go get xxx@latest),如果 xxx 是个间接依赖包被其它包所依赖时,并且这些包所需要的 xxx 版本为老版本并且新老版本不兼容的话,会使得编译不通过。
可以使用 go get xxx@vmajor.minor.patch 获取特定的依赖包。

module 允许同时依赖于某个包的不同主版本,但是特定主版本最多只能有一个。例如:可以同时依赖 xxx 的 v1 和 v2两个版本,但不能同时依赖 v1 版本中的 v1.0.0 和 v1.0.1。
当依赖多个主版本时使用 semantic import versioning 进行指定。例如:rsc.io/quote 表示 v1 版,rsc.io/quote/v2 表示 v2 版。

allowing different major versions of a module (because they have different paths) gives module consumers the ability to upgrade to a new major version incrementally

可以看出之所以可以这样是因为不同的主版本的路径必须是不同的,例如:rsc.io/quote 和 rsc.io/quote/v2 是两个路径。

这样引入了一条规则:

If an old package and a new package have the same import path,
the new package must be backwards compatible with the old package.

所以对于 github/user/xxx 的开发者来说,当他想开发第二个版本时,必须把 v2 版的代码提交到 github/user/xxx/v2 路径下(两个路径下都是完整的 module,分别有各自的 go.mod ),这样使用者就可以有选择的使用。
官方说使用版本后缀的方式管理包,是 go 有别于其他工具的地方,这样可以解决菱形依赖问题。

$ pwd
/.../xxx
$ ls
README.md   one.go  two.go  ...
$ cat go.mod
module github.com/hengzi52125/xxx
go 1.13
require (
    ...
)
$
$
$ mkdir v2
$ cp *.go v2/
$ cp go.mod v2/go.mod
$ go mod edit -module github.com/hengzi52125/xxx/v2 v2/go.mod

依赖包会被下载到 $GOPATH/pkg/mod/ 目录下,并带有版本标记(例如:$GOPATH/pkg/mod/github.com/nfnt/resize@v0.0.0-20180221191011-83c6a9932646),当下次另外的 module 用到同样的包时不会重复下载。

对于未被 tag 的包(例如上面的 nfnt/resize 包,只有个 master 分支,而且没有 Tag ),go 命令会自动生成个 preudo version 版本号, 如:v0.0.0-yyyymmddhhmmss-abcdef 时间为 commit UTC时间,abcdef 为 commit hash。

go.sum 文件列出依赖包的源码的 SHA-256 哈希值,主要用于验证从 GOPROXY 镜像站点上下载下来的代码有没有被做篡改,保证安全。
所以 GOSUMDB 没有镜像站点,鉴于国内网络只能关闭该检查功能,即 GOSUMDB="off"

使用 go mod init xxx 会自动创建 go.mod 文件,当下载依赖后会自动创建 go.sum 文件。所以这两个文件一般不需要手动创建。

GOPROXY 和 GOSUMDB


GOPROXY 协议流程:

proxy-protocol 来源于官方文档

设置国内镜像站点 https://goproxy.cn :
go env -w GOPROXY="https://goproxy.cn,https://proxy.golang.org,direct"

GOSUMDB 协议流程:

sumdb-protocol 来源于官方文档

关闭 GOSUMDB:
go env -w GOSUMDB="off"

go.mod 文件


module:指定本 module 的名字(路径)

如果不是第一个主版本,如: v0 或 v1,则要在后面加上版本后缀

module github.com/hengzi52125/xxx/v2

require:指定依赖

多个依赖可以放在一个 "()" 里,就像 import 那样

require (
    dependency1
    dependency2
)

replace:替换依赖

当某些原因导致 require 中的依赖下载不下来时,或者想导入本地的包时,可以使用 replace

replace (
    golang.org/x/image vx.y.z => github.com/golang/image vx.y.z
    a-package vx.y.z => /Users/...
)

exclude:排除依赖

举个栗子:假设在代码中 import github.com/user/xxx, 对于这个 xxx 它现在最新的版本是 v1.1.1 , 但是你不想用 v1.1.1, 于是就可以把它放入 exclude 中

exclude github.com/user/xxx v1.1.1

使用


创建 module
go mod init github.com/hengzi52125/xxx

导入依赖
正常编写代码,当执行 go test/run/build 等命令时会自动导入最新的依赖包(“Latest” is defined as the latest tagged stable (non-prerelease) version, or else the latest tagged prerelease version, or else the latest untagged version.)

go get foo@v1.2.3 可以导入特定版本的依赖,@ 后面可以跟 git 的 branch、tag、commit hash。如果使用的是分支,如:go get foo@master 那么只会下载一次,即下次执行 go get foo@master 时不会再去下载,直接用本地的,即使 master 上代码有更新。

go mod download : 下载依赖包

查看依赖
go list -m all :会列出当前的 module 和它所有的依赖(包括间接依赖)

go list -m -versions xxx :列出 xxx 的所有版本

go doc xxx/v3 :查看文档

go mod graph :打印模块依赖图

清除无用的依赖
go mod tidy :清除未被使用的依赖,或导入所需依赖(导入最新的版本)

升降级依赖
go list -u -m all :升级并查看所有依赖(go list -u 只能搭配 -m 才能使用)

go get -u xxx :升级 minor 或 patch 版本号

go get -u=patch xxx :只升级 patch 版本号

go get xxx@'<vx.y.z' : 使用大于小于等比较运算符进行升降级

格式化 go.mod
go mod edit -fmt :如果手动修改了 go.mod 变得格式不美观了,可以用其格式化

参考链接


preudo-version
Go Modules: v2 and Beyond
Publishing Go Modules
Module Mirror and Checksum Database Launched
Using Go Modules

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,914评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,935评论 2 383
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,531评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,309评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,381评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,730评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,882评论 3 404
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,643评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,095评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,448评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,566评论 1 339
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,253评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,829评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,715评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,945评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,248评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,440评论 2 348

推荐阅读更多精彩内容