问题 | golang开发之go.mod的使用方法


go mod之坑

背景

这是二次修改,原因是,我隔了一段时间没有编程,现在有需要再重新执笔,下载了一个第三方的开源项目,结果原作者是在gopath里面开发的,那么到了21世纪的今日,go都版本都去到15了。我怎么不能用mod去管理版本呢。而且重要的一点,开发一定要在gopath里面进行开发,这个超级不方便的嘛。

结果蒙蔽了,我不懂了,重新看回这边当初写过的文章。什么鬼。屎一般的存在。

go的版本为:go version go1.14.4 windows/amd64

编码工具为vscode
goproxy在国内有三个可用的
https://goproxy.io
https://goproxy.cn
https://mirrors.aliyun.com/goproxy/

项目

随便找个go开发的开源项目,如果你不想找,看如下链接:
https://github.com/Adminisme/ServerScan
整个打包下载回来即可。

自己开发的程序目录架构,也是可以的,主要A目录里面包含B目录,B目录里面包含C目录。
A是主程序,B是模块,C是B的模块。
简单理解:A是爷爷,B是爸爸,C是儿子。

特别注意的是:
一个项目只需要有一个mod即可

mod实战

一个项目只需要使用一个mod即可
上面这句话真的很重要。

主程序调用同目录里面的包

1、当你按照我刚刚提供的一个开源项目,下载回来解压后,项目是这样的:
在这里插入图片描述
PS:这里需要解释一下,ServerScan这个开源的项目里面,包含了三个独立功能的项目。要知道,go的话一个项目只认一个main文件。所以每个独立功能项目里面作者可能基于什么原因又弄了两个版本。我们进入了其中一个项目里面,轻便版扫描。

2、我们进入到子模块文件夹。
在这里插入图片描述
PS:在vscan子模块文件夹里面还有子模块。一环套一环。

3、了解完整个项目结构之后,真正需要使用go mod版本来进行管理了。这里我们要在主程序的目录下,使用命令初始化go mod管理。
命令是:go mod init
在这里插入图片描述
4、这里我们需要记住的是,当前程序我们已经通过init成立了一个包,包的名字是:scanAir,也就是说,这个主程序里面包含的所有模块都会由这个包scanAir来控制并管理。

5、实际上我们init后,是不需要去打开和管理这个mod文件的。我们在主程序中,添加一下B模块(爸爸)。
在这里插入图片描述
上图是原作者,导入自己开发的子模块方法。

下面是我们用了go mod后导入自己开发的模块(包)方法。
在这里插入图片描述
PS:这里只是主程序调用第二层的子模块,像上面我们了解到的,B模块,它自身也需要再调用C模块,那这里的话,应该按照主程序调用B模块的讨论继续往下写即可,如:A包名/B模块名称/C模块名称。
在这里插入图片描述

主程序调用其他目录的包

1、主程序在C盘,想调用D盘的子包;情况就是,主程序需要mod文件,D盘的子包也需要mod文件。
在这里插入图片描述

2、打开主程序的mod文件,进行修改。
主要修改使用到的两个关键字:requirereplace

require icmpcheck v0.0.0
replace icmpcheck => D:\code\icmpcheck

在这里插入图片描述
3、直接导入包即可。
在这里插入图片描述

重要提醒

使用开源的项目,要注意原作者使用的第三方库,我们需要人工或者配置好go mod 之后下载这些库才行。

库是包含了很多个包的。
一个项目里面,称为一个库,库里面可以设计成很多个模块(包)。

问答FAQs

1. 有些包由于特定网络原因无法访问怎么办?

Go module 加入了代理的机制,只要设置一个代理地址,就可以提供代理访问。阿里云就提供了这样一个go 的代理,是完全免费的服务。公共代理仓库会代理并缓存go模块,你可以利用该代理来避免 DNS 污染或其他问题导致的模块拉取缓慢或失败的问题,加速你的项目构建。

设置的方式非常简单,只需要设置如下环境变量即可,执行命令:
linux下:export GOPROXY=https://mirrors.aliyun.com/goproxy/
windows下:set GOPROXY=https://mirrors.aliyun.com/goproxy/

go1.13 加入了 mirror 机制,可以通过 go env -w 设置 mirror,其实就是之前的 GOPROXY 做的更到位一些,执行命令:
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct

经过测试,要goproxy的地址存在才行,如果你的goproxy是xxx.com,这里又写了aaa.cn,会提示覆盖错误的。

逗号后面可以增加多个 proxy,最后的 direct 则是在所有 proxy 都找不到的时候,直接访问,代理访问不到的私有仓库就可以正常使用了。

这个功能基本上是在家远程办公的必备工具了。

2. 公司通过 gitlab 搭建了私有库,二方依赖库下载不下来怎么办?

这个几乎是最常见的问题,比较简单的解决方案是 hack 一下 git 配置:

git config --global url."git@gitlab.your-company.com:<your>/<package>.git".insteadOf "https://gitlab.your-company.com/<your>/<package>.git"

这个方案依赖你本地的~/.ssh/id_rsa, 这样你就可以正常 go get 了。

3. 依赖包怎么更新指定版本?

先查看版本:

$ go list -m -versions rsc.io/sampler
rsc.io/sampler v1.0.0 v1.2.0 v1.2.1 v1.3.0 v1.3.1 v1.99.99

再更新:

$ go get rsc.io/sampler@v1.3.1
go: finding rsc.io/sampler v1.3.1
go: downloading rsc.io/sampler v1.3.1
go: extracting rsc.io/sampler v1.3.1
$ go test
PASS
ok      example.com/hello    0.022s
4. 某些依赖包的地址变更导致无法找到了怎么办?

go 的依赖与项目名直接相关,这就导致如果我们使用了 github 上的项目,然后项目的维护人员突发奇想改个项目名称,就会导致所有依赖它的项目都无法找到依赖。

还好有 replace 的机制:

replace golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a => github.com/golang/crypto v0.0.0-20190313024323-a1f597ede03a
5. 版本冲突怎么办?

这就要梳理版本了,是最没有捷径的。一个比较简单的办法是把所有 go.mod 里不需要指定版本的包全部删掉,仅指定必要的包版本,然后通过 go build 让项目自动构建依赖包的版本。

通过 go mod graph 可以查看具体依赖路径:

$ go mod graph
github.com/oam-dev/oam-go-sdk github.com/go-logr/logr@v0.1.0
github.com/oam-dev/oam-go-sdk github.com/onsi/ginkgo@v1.10.1
github.com/oam-dev/oam-go-sdk github.com/onsi/gomega@v1.7.0
github.com/oam-dev/oam-go-sdk github.com/stretchr/testify@v1.4.0
github.com/oam-dev/oam-go-sdk golang.org/x/net@v0.0.0-20191004110552-13f9640d40b9
github.com/oam-dev/oam-go-sdk k8s.io/api@v0.17.0
github.com/oam-dev/oam-go-sdk k8s.io/apimachinery@v0.17.0
github.com/oam-dev/oam-go-sdk k8s.io/client-go@v0.17.0
github.com/oam-dev/oam-go-sdk sigs.k8s.io/controller-runtime@v0.4.0
...

左边是项目包,右边是被依赖的包和版本。

如果确实存在两个需要指定版本的包互相冲突,那就要做取舍,修改代码,升级或降级某个包了。

6. 本地包如何引用?

如果在代码调试过程中,涉及到修改其他依赖项目代码,这时候就要引用本地包,也可以采用 replace 机制:

require (
    golang.org/x/crypto v0.0.0
)
replace golang.org/x/crypto v0.0.0 => ../crypto
...

后面这个就是个相对项目路径的本地依赖所在路径。

解决了上面的这些问题,基本上你就可以愉快的使用 module 功能啦。

go mod 里还有一些其他功能,也在此列举,方便大家查阅:

go mod 子命令功能
downloaddownload modules to local cache(下载依赖包)
editedit go.mod from tools or scripts(编辑 go.mod)
graphprint module requirement graph(打印模块依赖图)
initinitialize new module in current directory(在当前目录初始化mod)
tidyadd missing and remove unused modules(拉取缺少的模块,移除不用的模块)
vendormake vendored copy of dependencies(将依赖复制到vendor下)
verifyverify dependencies have expected content(验证依赖是否正确)
whyexplain why packages or modules are needed(解释为什么需要依赖)
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值