前言
如果你接触go语言比较早,一定有过当年所有go源码全部放入 GOPATH
下的混乱经历,不过发展到今天,go的包管理使用 go.mod
和 go.work
已经能得心应手,满足绝大多数的开发不成问题,其实在 go.mod
引入之后,go的包管理就有了明显的改善,再也不像原来那样好似闹着玩一样了,关于go.mod使用和管理我也是一知半解,想要教程可去官网或者查找各种详解资料,只是最近有点疑惑,这个go.mod以及go.sum要不要自己手动管理,带着这个疑问我做了一些测试可以得出,go.mod 的最初不需要手动管理,如果后来需要调整引入包的版本,可以手动调整。
以下是来自ChatGPT的关于 go.mod
和 go.sum
作用的回答,还是比较清晰的,如果还不太明白可以看看后面的例子感受一下
go.mod
和go.sum
文件是 Go Modules 的重要组成部分,用于管理项目的依赖关系。共同为 Go 项目提供了依赖管理的基础,确保了项目的稳定性和可维护性:
go.mod:
- 定义了项目的模块信息,包括模块名称、版本和依赖项等。
- 确定了项目的模块根目录。
- 记录了项目所依赖的其他模块及其版本信息。
- 提供了一种清晰的方式来管理项目的依赖关系,使得项目的构建和维护更加可靠和可控。
go.sum:
- 记录了每个依赖模块的哈希值,以保证项目的构建是可复现的。
- 确保了项目依赖项的完整性,防止恶意篡改或不完整的依赖项被用于构建项目。
- 当使用
go mod verify
命令时,go.sum
文件会被用来验证依赖项的完整性。
>
通常情况下,
go.mod
文件是由go
工具自动生成和管理的,不需要手动修改。当你执行一些与模块相关的操作时(例如使用go get
安装新的依赖、使用go mod tidy
整理依赖、或者更新依赖版本等),go
工具会自动更新go.mod
文件以反映这些变化,但是,在某些特定情况下,你可能需要手动编辑go.mod
文件,例如:
手动添加或删除依赖项:你可能希望手动添加新的依赖项,或者删除不再需要的依赖项。在这种情况下,你需要手动编辑
go.mod
文件,并执行go mod tidy
命令以确保依赖关系的一致性。手动指定依赖版本:有时你可能希望显式地指定某个依赖项的特定版本。在这种情况下,你需要编辑
go.mod
文件,并指定对应的版本号。总的来说,虽然
go.mod
文件通常是由go
工具自动维护的,但在某些情况下手动编辑是必要的。在编辑go.mod
文件时,确保遵循 Go 模块的规范,并注意保持文件的格式正确和依赖关系的一致性。
具体示例
假设有一个需求,要读取 .xlsx
格式表格文件的所有页签名,解析Excel文件这么基础的工作肯定有人写好了,我们直接引入module不需要重新再写一遍了,我们新建一个包含go.mod的工程来使用它
1 | $ mkdir lib_xlsx |
go.mod的初始文件内容为
1 | module lib_xlsx |
打开 lib_xlsx.go
文件编写如下代码:
1 | package main |
代码是不是很简单,此时不出意外IDE会提醒你 could not import github.com/tealeg/xlsx
的错误,因为我们还没下载这个包,只需要在命令行执行 go get github.com/tealeg/xlsx
既可下载,同时会自动更新 go.mod
和 go.sum
文件
1 | $ go get github.com/tealeg/xlsx |
自动更新后的 go.mod 文件内容,引用了 github.com/tealeg/xlsx
库的 v1.0.5
版本
1 | module lib_xlsx |
自动更新后的 go.sum 文件内容,记录了各个依赖库、间接依赖库以及项目go.mod文件的hash值
1 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= |
此时程序已经写完,依赖关系也已经下载好了,直接运行就可以
1 | $ go run . |
因为 go.mod
和 go.sum
文件共同为这个项目提供了依赖管理,别人在下载你这份源码时,先执行 go mod tidy
根据依赖关系下载正确的版本库,之后就可以直接编译运行了
手动升级依赖库
到目前为止,我们并没有手动编辑过 go.mod 文件,只是在使用 go get github.com/tealeg/xlsx
自动更新了这个文件,假设这个例子的需求要扩展,引用的 github.com/tealeg/xlsx
功能是在v1.0.6
版本新加的,那么我么只需要将 go.mod
文件中的 v1.0.5
替换成 v1.0.6
,然后执行 go mod tidy
即可下载正确的依赖库。
但如果要引用的依赖库版本不是 v0
或者 v1
版本的就不能这么处理了,具体做法看下面的问题。
should be v0 or v1, not v2
当你手动把 go.mod
文件中的 v1.0.5
替换成 v2.x.x
执行 go mod tidy
时就会报一个错误
errors parsing go.mod: /xxx/lib_xlsx/go.mod:5: require github.com/tealeg/xlsx: version “v2.0.0” invalid: should be v0 or v1, not v2
问题的原因及细节可以参考这篇文档《[Go] 到底 go get 的版號怎麼運作的?》中关于“Semantic import version”的描述
复杂的原因简单说:Go有一个规范,就是在启用了Go Module的仓库上如果想使用 v2 及以上版本,需要在原引用库上添加版本标识简写,比如这个例子中,我们需要将 lib_xlsx.go
文件中引用包的代码改成下面这样
1 | import ( |
执行 go mod tidy
命令
1 | $ go mod tidy |
如果遇到下面这个问题,确认修改无误的话多尝试几次
$ go mod tidy
go: finding module for package github.com/tealeg/xlsx/v3
lib_xlsx imports
github.com/tealeg/xlsx/v3: module github.com/tealeg/xlsx/v3: Get “https://proxy.golang.org/github.com/tealeg/xlsx/v3/@v/list“: EOF
执行过后 go.mod 和 go.sum 两个文件改变后的内容如下:
1 | module lib_xlsx |
1 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= |
将 github.com/tealeg/xlsx 从 v1.0.5
升级到 v3.3.5
真是加了不少间接依赖库啊
至此 go.mod 文件的自动更新和手动维护我们就都尝试过了
总结
go.mod
和go.sum
文件是 Go Modules 的重要组成部分,用于管理项目的依赖关系go.mod
文件是由go
工具自动生成和管理的,不需要手动修改,常用命令go get xxx
和go mod tidy
- 如果想显式地指定某个依赖项的特定版本才需要手动编辑
go.mod
文件 go.sum
文件记录了每个依赖模块的哈希值,以保证项目的构建是可复现的- 如果在启用了Go Module的仓库想使用 v2 及以上版本,需要在原引用库路径末尾添加版本标识简写,比如v2、v3等
穷则独善其身,达则兼济天下,如今在这纷繁的世间,独善其身已实属不易,天下交给你们,我自顺其自然吧~
2024-2-8 15:59:19