#go modules模式
GOPATH模式下第三方库都必须放置在$GOPATH/src下才可以使用,并且当多个项目依赖第三方库的不同版本时,很容易引起混乱
go modules模式是一种全新的package管理模式,它以module的方式来组织和管理package
在go modules模式下:
- 一个module包含一个或者多个package。module 是多个 package 的集合,版本管理的基本单元
- go.mod记录依赖的module。使用go.mod文件记录当前module依赖的所以第三方module
- 使用go.sum记录依赖的每个第三方module的版本和哈希值
- import的是package,这些package哪里来呢?要么是go自带的package,要么就是go.mod记录的依赖的module提供的package
- 在go modules模式下,依赖的第三方module源码默认会下载到$GOPATH/pkg/mod目录
#go.mod 文件
go.mod文件是go modules模式的核心文件
go.mod 位于项目的根目录,支持 4 条命令:module、require、replace、exclude。示例:
module github.com/my/repo
require (
github.com/some/dependency v1.2.3
github.com/another/dependency/v4 v4.0.0
)
- module 声明 module path,一个 module 内所有 package 的 import path 都以它为前缀
假如一个 module 有如下目录结构,go.mod 采用上面的示例
repo
|-- bar
| `-- bar.go
|-- foo
| `-- foo.go
`-- go.mod
那么 bar 包的 import path 即为:
import "github.com/my/repo/bar"
- require 声明所依赖的 module,版本信息使用形如
v(major).(minor).(patch)
的语义化版本 semver,比如:v0.1.0 - replace/exclude 用于替换、排查指定 module path
更多参考 https://liujiacai.net/blog/2019/10/24/go-modules/
#go mod 常用命令
go mod 是 go modules 模式下的依赖管理命令前缀
go mod init # 初始化go.mod
go mod download # 下载依赖文件。根据go.mod文件下载所有依赖的模块到本地缓存中,本地缓存的默认路径是$GOPATH/pkg/mod目录
go mod tidy # 更新依赖文件
go mod vendor # 将依赖转移至本地的vendor文件
go mod edit # 手动修改依赖文件
go mod graph # 打印依赖图
go mod verify # 校验依赖
go mod why # 解释为什么需要依赖
注意:
go mod init module_path
if your module will be imported by other modules, the module path should reflect its published location, where Go tools could find it to download it
如果你的module需要被其他module引入,那么你的module path必须指向module源码存放的位置。比如你的go.mod首行声明了module github.com/google/uuid
,那么这个module的源码就须对应存放到github.com/google/uuid这个地址下
->顾名思义嘛,module path~
当然啦,也可以在go.mod中使用replace
来规避这些问题
replace 代码中引用的module路径 => module存放的真实路径
go.mod 的 replace 主要用于替换 module path,这对于引用本地依赖非常有帮助。比如有一个库 github.com/user/lib 有 bug,你需要 fork 到本地去修复,这时在自己的项目中需要引用本地 fork 的分支,那么就可以这么用,而保持代码里面的 import path 不变:
replace github.com/user/lib => /some/path/on/your/disk
类似的原理,项目的 module 名字,也不必加上托管平台前缀了。比如我创建了一个示例项目 [demo],托管在https://github.com/xxx/demo,其 go.mod 如下:
module demo
go 1.15
如果要引用这个项目,只需要这么做:
// go.mod
replace demo => github.com/xxx/demo
// demo_test.go
import demo
func TestModule(t *testing.T) {
demo.Hello("hello")
}
#go mod download
和 go mod tidy
的区别
go mod download
is downloading all of the modules in the dependency graph, which it can determine from reading only the go.mod file. It doesn't know which of those modules are actually needed to satisfy a build, so it doesn't pull in the checksums for those modules (because they may not be relevant).
go mod download
只依据go.mod去下载依赖,而不关心这些依赖是否仍然被项目需要
On the other hand,
go mod tidy
will download all the dependencies that are required in your source files and update go.mod file with that dependency.go mod tidy
has to walk the package graph in order to ensure that all imports are satisfied. So it knows, for a fact, without doing any extra work, that the modules it walks through are needed for a go build in some configuration. see https://golangbyexample.com/go-mod-tidy/
go mod tidy
会整理项目的依赖关系后,再去下载
一般使用go mod tidy
来更新项目的依赖项
#GOPROXY
GOPROXY 是Go官方提供的一种通过中间代理来为用户提供包下载服务的方式
eg. go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct
// ps:【七牛云】为中国的gopher提供了一个免费合法的代理goproxy.cn
go env -w GOPROXY=https://goproxy.cn,direct
#go mod依赖管理的内部原理
关于go modules 模式下,module管理机制的原理图示如下:
gomod.png
网友评论