Go Modules的前世今生
以前,Go语言的依赖包的管理一直被诟病,Go官方从最初的GOPATH到GO VENDOR,再到目前的GO Modules,一直在努力提供更方便的包管理方案。
目前最主流的方案是官方推荐的GO Modules。先介绍一下以前的GOPATH和GO VENDOR,了解它们的发展历程,才能知道GO Modules多么来之不易。
1、 古老的GOPATH
配置环境的时候对其应该都不陌生,可以将其理解为“工作目录”。
工作目录下通常有如下目录:
将自己或者别人的包全部放在$GOPATH/src目录下来管理的方式,就称为GOPATH模式。
在此模式下,使用go install,生成的可执行文件会放在$GOPATH/bin下。
如果安装的是一个库,则会生成.a 文件到 $GOPATH/pkg 下对应的平台目录中。
使用GOPATH去开发程序有个最严重的问题,就是版本管理问题,因为GOPATH根本没有版本的概念。
会遇到的问题:
u 无法在你的项目中,使用指定版本的包,因为不同版本的包的导入方法都一样;
u 其他人运行你的开发的程序时,无法保证他下载的包版本是你所期望的版本,当对方使用了其他版本,有可能导致程序无法正常运行
u 在本地,一个包只能保留一个版本,意味着你在本地开发的所有项目,都得用同一个版本的包,这几乎是不可能的
2、 Go vendor模式的过渡
为了解决GOPATH模式下不同项目下无法使用多个版本库的问题,Golang从v1.5开始支持vendor。
以前使用GOPATH的时候,所有项目都共享一个GOPATH,需要依赖的时候,都来这里找,在GOPATH模式下只能有一个版本的三方库。
Vendor模式的思路就是为每个项目都创建一个vendor目录,每个项目的依赖都下载到自己的vendor目录下,项目之间的依赖包互不影响。编译时,默认开启vendor特性,相较于GOPATH,提升vendor目录的依赖包搜索路径的优先级。
搜索包的优先级顺序:
(1) 当前包下的vendor目录‘
(2) 向上级目录查找,直到找到src下的vendor目录;
(3) 在GOROOT目录下查找;
(4) 在GOPATH下面查找依赖包
此方案的不足:
(1) 如果多个项目用到了同一个包的同一个版本,这个包会存在于该机器上的不同目录下,不仅对磁盘空间是一种浪费,而且没法对第三方包进行集中式的管理(分散在各个角落)。
(2) 如果要分享开源你的项目,你需要将你的所有的依赖包悉数上传,别人使用的时候,除了你的项目源码外,还有所有的依赖包全部下载下来,才能保证别人使用的时候,不会因为版本问题导致项目不能如你预期那样正常运行。
3、 Go mod的横空出世
go modules 在 v1.11 版本正式推出,在最新发布的 v1.14 版本中,官方正式发话,称其已经足够成熟,可以应用于生产上。
从 v1.11 开始,go env多了个环境变量: GO111MODULE,这里的 111,其实就是 v1.11 的象征标志, go 里好像很喜欢这样的命名方式,比如当初 vendor 出现的时候,也多了个GO15VENDOREXPERIMENT环境变量,其中 15,表示的vendor 是在 v1.5 时才诞生的。
GO111MODULE 是一个开关,通过它可以开启或关闭 go mod 模式。
它有三个可选值:off、on、auto,默认值是auto。
(1)GO111MODULE=off禁用模块支持,编译时会从GOPATH和vendor文件夹中查找包。
(2)GO111MODULE=on启用模块支持,编译时会忽略GOPATH和vendor文件夹,只根据 go.mod下载依赖。
(3)GO111MODULE=auto,当项目在$GOPATH/src外且项目根目录有go.mod文件时,自动开启模块支持。
开启go mod就将GO111MODULE设置为on。比如可以:
go env –w GO111MODULE=”on”
4、 go mod依赖的管理
初始化时,会多出go.mod文件;执行安装,会下载依赖包并且完善go.mod文件生成go.sum文件。
go mod会将下载的依赖包都安装到$GOPATH/pkg下,生成的可执行文件在$GOPATH/bin下。
go.mod和go.sum是go modules的核心所在。
² go.mod:
go.mod的内容比较容易理解,第一行就是模块的引用路径,第二行就是项目所用的go版本,第三行就是项目所需的直接依赖包及版本。
有时会看到更加复杂的go.mod文件:
exclude表示忽略指定版本的依赖包,replace表示替换库。
² go.sum:
go.sum文件比较复杂:
每一行其实都是由模块路径、模块版本、哈希检验值 组成的。哈希检验值是用来保证当前缓存的模块不会被篡改。Hash是以h1:开头的字符串,表示生成检验值的算法是第一版的哈希算法。
值得注意的是,有点包只有一行,有的包有两行:
有两行的包,区别在于hash不一致,一个是h1:hash, 一个是go.mod h1:hash。h1:hash和go.mod h1:hash要不就是同时存在,要不就是只有go.mod h1:hash。什么情况下会没有h1:hash呢?就是当GO认为肯定用不到某个模块版本的时候就会省略它的h1:hash。
go.mod 和 go.sum 是 go modules 版本管理的指导性文件,因此 go.mod 和 go.sum 文件都应该提交到Git 仓库中去,避免其他人使用你的项目时,重新生成的go.mod 和 go.sum 与你开发的基准版本的不一致。
5、 go mod命令的使用
u go mod init
初始化go mod,生成go.mod文件,后可以接参数指定module名。
u go mod download
手动触发下载依赖包到本地缓存(默认$GOPATH/pkg/mod目录)
u go mod graph
打印项目的模块依赖结构
u go mod tidy
添加缺少的包,删除无用的包
u go mod verify
校验模块是否被篡改过
u go mod why
查看为什么需要依赖
u go mod vendor
导出项目的所有依赖到vendor下
u go mod edit
编辑go.mod文件,接 -fmt 参数格式化 go.mod 文件,接 -require=golang.org/x/text 添加依赖,接 -droprequire=golang.org/x/text 删除依赖,详情可参考 go help mod edit
u go list –m –json all
以 json 的方式打印依赖详情
6、 如何给项目添加依赖写进go.mod
法(1):只要在项目中import,然后go build,go module就会自动下载并添加;
法(2):自己手动使用go get下载安装后,会自动写入go.mod
本文来自博客园,作者:易先讯,转载请注明原文链接:https://www.cnblogs.com/gongxianjin/p/17535127.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具