1. 先说go get
非$GOPATH
目录下的go mod
项目
➜ abc go mod init
go: creating new go.mod: module github.com/abc
➜ abc ls
go.mod
➜ abc cat go.mod
module github.com/abc
go 1.16
➜ abc go get github.com/jinzhu/gorm
go: downloading github.com/jinzhu/gorm v1.9.16
go get: added github.com/jinzhu/gorm v1.9.16
➜ abc cat go.mod
module github.com/abc
go 1.16
require github.com/jinzhu/gorm v1.9.16 // indirect
可见,在go mod
初始化的项目目录下执行go get package
,会将package
下载到$GOPATH/pkg
目录下安装,并且添加或更新到go.mod文件中
当想要修改 package
的版本时,只需要go get package@指定的version
, go.mod
也会相应的更新
非go mod
项目,非含有go.mod的目录
1.16无效
$ pwd
/Users/sunnky/go/src/github.com/jinzhu
$ ls
inflection now
$ go get github.com/jinzhu/gorm
$ ls
gorm inflection now
非go mod
项目,执行go get package
,只是将package
下载到$GOPATH/src/...
目录下安装到$GOPATH/src
2. 发布自己的包
https://blog.csdn.net/MrKorbin/article/details/111032300
3. go mod详解
https://blog.csdn.net/qq_34021712/article/details/109146367
4. go mod中的 // indirect
在使用 Go module 过程中,随着引入的依赖增多,也许你会发现go.mod
文件中部分依赖包后面会出现一个// indirect
的标识。这个标识总是出现在require
指令中,其中//
与代码的行注释一样表示注释的开始,indirect
表示间接的依赖。
比如开源软件 Kubernetes(v1.17.0版本)的 go.mod 文件中就有数十个依赖包被标记为indirect
:
require (
github.com/Rican7/retry v0.1.0 // indirect
github.com/auth0/go-jwt-middleware v0.0.0-20170425171159-5493cabe49f7 // indirect
github.com/boltdb/bolt v1.3.1 // indirect
github.com/checkpoint-restore/go-criu v0.0.0-20190109184317-bdb7599cd87b // indirect
github.com/codegangsta/negroni v1.0.0 // indirect
...
)
在执行命令go mod tidy
时,Go module 会自动整理go.mod
文件,如果有必要会在部分依赖包的后面增加// indirect
注释。一般而言,被添加注释的包肯定是间接依赖的包,而没有添加// indirect
注释的包则是直接依赖的包,即明确的出现在某个import
语句中。
然而,这里需要着重强调的是:并不是所有的间接依赖都会出现在 go.mod
文件中。
间接依赖出现在go.mod
文件的情况,可能符合下面所列场景的一种或多种:
- 直接依赖未启用 Go module
- 直接依赖go.mod 文件中缺失部分依赖
直接依赖未启用 Go module
如下图所示,Module A 依赖 B,但是 B 还未切换成 Module,也即没有go.mod
文件,此时,当使用go mod tidy
命令更新A的go.mod
文件时,B的两个依赖B1和B2将会被添加到A的go.mod
文件中(前提是A之前没有依赖B1和B2),并且B1 和B2还会被添加// indirect
的注释。
此时Module A的go.mod
文件中require部分将会变成:
require (
B vx.x.x
B1 vx.x.x // indirect
B2 vx.x.x // indirect
)
依赖B及B的依赖B1和B2都会出现在go.mod
文件中。
直接依赖 go.mod 文件不完整
即便B拥有go.mod
,如果go.mod
文件不完整的话,Module A依然会记录部分B的依赖到go.mod
文件中。
如下图所示,Module B虽然提供了go.mod
文件中,但go.mod
文件中只添加了依赖B1,那么此时A在引用B时,则会在A的go.mod
文件中添加B2作为间接依赖,B1则不会出现在A的go.mod
文件中。
此时Module A的go.mod
文件中require部分将会变成:
require (
B vx.x.x
B2 vx.x.x // indirect
)
由于B1已经包含进B的go.mod
文件中,A的go.mod
文件则不必再记录,只会记录缺失的B2。
为什么要记录间接依赖
在上面的例子中,如果某个依赖B 没有go.mod
文件,在A 的go.mod
文件中已经记录了依赖B及其版本号,为什么还要增加间接依赖呢?
我们知道Go module需要精确地记录软件的依赖情况,虽然此处记录了依赖B的版本号,但B的依赖情况没有记录下来,所以如果B的go.mod
文件缺失了(或没有)这个信息,则需要在A的go.mod
文件中记录下来。此时间接依赖的版本号将会跟据Go module的版本选择机制确定一个最优版本。
如何处理间接依赖
综上所述间接依赖出现在go.mod
中,可以一定程度上说明依赖有瑕疵,要么是其不支持Go module,要么是其go.mod
文件不完整。
由于Go 语言从v1.11版本才推出module的特性,众多开源软件迁移到go module还需要一段时间,在过渡期必然会出现间接依赖,但随着时间的推进,在go.mod
中出现// indirect
的机率会越来越低。
出现间接依赖可能意味着你在使用过时的软件,如果有精力的话还是推荐尽快消除间接依赖。可以通过使用依赖的新版本或者替换依赖的方式消除间接依赖。
如何查找间接依赖来源
Go module提供了go mod why
命令来解释为什么会依赖某个软件包,若要查看go.mod
中某个间接依赖是被哪个依赖引入的,可以使用命令go mod why -m <pkg>
来查看。
比如,我们有如下的go.mod
文件片断:
require (
github.com/Rican7/retry v0.1.0 // indirect
github.com/google/uuid v1.0.0
github.com/renhongcai/indirect v1.0.0
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/text v0.3.2
)
我们希望确定间接依赖github.com/Rican7/retry v0.1.0 // indirect
是被哪个依赖引入的,则可以使用命令go mod why
来查看:
[root@ecs-d8b6 gomodule]# go mod why -m github.com/Rican7/retry
# github.com/Rican7/retry
github.com/renhongcai/gomodule
github.com/renhongcai/indirect
github.com/Rican7/retry
上面的打印信息中# github.com/Rican7/retry
表示当前正在分析的依赖,后面几行则表示依赖链。github.com/renhongcai/gomodule
依赖github.com/renhongcai/indirect
,而github.com/renhongcai/indirect
依赖github.com/Rican7/retry
。由此我们就可以判断出间接依赖github.com/Rican7/retry
是被github.com/renhongcai/indirect
引入的。
另外,命令go mod why -m all
则可以分析所有依赖的依赖链。
5. GOPROXY中direct的作用
GOPROXY 这个环境变量主要是用于设置 Go 模块代理,主要如下:
它的值是一个以英文逗号 “,” 分割的 Go module proxy 列表
作用:用于使 Go 在后续拉取模块版本时能够脱离传统的 VCS 方式从镜像站点快速拉取。它拥有一个默认:https://proxy.golang.org,direct,但很可惜 proxy.golang.org 在中国无法访问,故而建议使用 goproxy.cn 作为替代。
可以执行语句:go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct
“direct” 为特殊指示符,用于指示 Go 回源到模块版本的源地址去抓取(比如 GitHub 等),当值列表中上一个 Go module proxy 返回 404 或 410 错误时,Go 自动尝试列表中的下一个,遇见 “direct” 时回源,遇见 EOF 时终止并抛出类似 “invalid version: unknown revision…” 的错误。
使用go env -w 写入的环境变量位置默认是
root用户下 /root/.config/go/env,也就是$HOME/.config/go/env