1.3 go mod最佳实践
javamavengogo mod

为什么要使用go mod?

  • 使用go mod仓库中可以不用再上传依赖代码包,防止代码仓库过大浪费以及多个项目同时用包时的浪费
  • 可以管理引用包的版本,这一点是gopath(src模式)和vendor做不到的
  • 如果依赖gopath不同项目如果引用了同一个软件包的不同版本,就会造成编译麻烦
src

原来的包管理方式

Go$GOPATH/srcsrc

新的包管理模式解决了以上问题

$GOPATH/srcgo.modreplace

1.3.1 配置 #

golang>=1.12GO111MODULEonauto
  • 打开go mod 模式
  • 使用国内下载包代理
  • 初始化mod项目
  • 自动增加包和删除无用包到 GOPATH 目录下(build的时候也会自动下载包加入到go.mod里面的)

注意:只要在本地设置一个公用path目录就可以了,全部的包都会下载到那里,其他本地项目用到时就可以共享了

自动生成了go.mod和go.sum文件,可以不用理会,下面是简单介绍

1.3.2 go.mod 文件 #

go.mod 的内容比较容易理解

  • 第一行:模块的引用路径
  • 第二行:项目使用的 go 版本
  • 第三行:项目所需的直接依赖包及其版本

在实际应用上,你会看见更复杂的 go.mod 文件,比如下面这样

主要是多出了两个 flag:

  • exclude:忽略指定版本的依赖包
  • replace:由于在国内访问golang.org/x的各个包都需要翻墙,你可以在go.mod中使用replace替换成github上对应的库。

注意上面的代码片段中出现了两个特殊的注释

incompatiblexxx.com/xxxxxx.com/xxx/v2indirect

1.3.3 go.sum 文件 #

每一行都是由 模块路径,模块版本,哈希检验值 组成,其中哈希检验值是用来保证当前缓存的模块不会被篡改。hash 是以h1:开头的字符串,表示生成checksum的算法是第一版的hash算法(sha256)。

值得注意的是,为什么有的包只有一行

而有的包却有两行呢

h1:hashh1:hash
h1:hashgo.modh1:hashgo.modh1:hashh1:hashh1 hashh1 hashgo.modh1:hash
go.modgo.sumgo.modgo.sumgo.modgo.sum

1.3.4 go mod 命令的使用 #

go mod init:初始化go mod, 生成go.mod文件,后可接参数指定 module 名,上面已经演示过。

go mod download:手动触发下载依赖包到本地cache(默认为$GOPATH/pkg/mod目录)

go mod graph:打印项目的模块依赖结构

go mod tidy :添加缺少的包,且删除无用的包

go mod verify :校验模块是否被篡改过

go mod why:查看为什么需要依赖

go mod vendor :导出项目所有依赖到vendor下

写入go.mod有两种方法:

go mod tidy

1.3.5 vendor是什么 #

vendor是项目缓存,为了防止开源代码项目被删除无法引用下载,会使用vendor来做缓存管理,它是独立的,你可以手动管理引用的包,代码包查找的顺序是向上冒泡

这样的话, 我们可以把包的依赖都放在 vendor 下,然后提交到仓库,这样可以省却拉取包的时间,并且相对自由,你想怎么改都可以

1.3.6 最佳实践 #

go mod 只是一个依赖包版本管理工具,包的查找顺序还是一样的,使用mod就不用把代码都放到src下来管理,可以根据go.mod文件中记录的版本来索引

我建议:

  • 使用mod管理版本,并使用go vendor来cache依赖包,上传到仓库防止代码包被删除
  • 运行时用到自己的项目,不要使用本地代码,而是保证依赖包都是稳定的,防止忘记提交
  • 如果你想发布包把自己写的模板给别人用,记得提交到仓库

这样就可以单个项目独立下来debug了,依赖包版本也管理上了

PS: go项目就可以使用mod和vendor,如果要集成其他语言代码为子模块可以使用git submodule

1.3.7 tips #

Q1: 我的包下哪去了?

$GOPATH/pkg/mod
GO111MODULEautoonoff
autosrcongo.modoffsrc

Q3: 依赖包中的地址失效了怎么办?比如 golang. org/x/… 下的包都无法下载怎么办?

go.modreplace
replace golang.org/x/text => github.com/golang/text latest
gogithub.com/golang/textgolang.org/x/text
go mod
go.modmodule mainmainimport "项目名/模块名"
Go 1.13

1.3.8 小结 #

go mod 是未来的默认模式,未来会取消 go path 也就是src 的方式,但自己的项目目录还是尽量按路径放置,不然回头找不到了

1.3.9 引用 #