如何学会使用 go modules,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
导读:go modules
是 golang 1.11 新加的特性。如今 1.13 都已经发布了第 7 个小版本了,几乎所有大项目均已开始使用,这自然也包括 Kubernetes 生态中的众多项目。笔者在开发 OAM 相关项目的时候,却发现 modules 的各项功能看似简单,却并没有那么好用,于是便想给大家分享一下使用心得。
简单说就是包管理,Golang 的包管理素来以混乱著称,以前是依赖 $GOPATH
,只要你的代码放在指定路径下就好了,完全没有“包管理”的概念。被社区吐槽了很久以后开始搞 vendor
机制,简单来说就是代码不光是可以放到指定路径,还可以放在项目自身路径的 vendor 文件夹。这个解决的问题是:你引用的代码包上游变更不会直接影响你的项目,这显然是开始关心“包版本”了。遗憾的是依旧没有解决包管理的问题,比如不同的包依赖了同一个包的不同版本怎么办?版本间代码冲突怎么办?vendor
机制并没有解决,于是围绕 vendor/
社区就出了几十个包管理工具,一时间百花齐放、百家争鸣、各有所长,导致 golang 的包管理生态变得有些混乱。对这段历史感兴趣的可以阅读下笔者曾经写的文章《Go 包管理的前世今生》。
更有意思的是,在 go 官方社区看到包管理工具的乱象后,也做了个功能类似的工具 dep
,原理与其他各类依靠vendor/
机制的包管理工具类似,准备对包管理做统一。当大家对 dep
工具报以期望并纷纷开始切换到 dep
工具管理依赖包的时候,go 官方又发布了现在的 modules 机制,完全放弃了之前的 dep
工具与 vendor
机制。这样的操作在社区引起了巨大的争议,modules 与 go get
、go build
等官方工具生态有很好的集成,官方的意图自然是希望抛开原有的历史包袱,通过全新的方式拯救世界。然而实际体验下来,却依旧不尽如人意。
总的来说大趋势已经是用 modules
,go1.13 也对 modules 机制做了不少工作。
言归正传,本文的目标是希望能用 5~10 分钟时间带您学会使用 go modules,然后通过 QA 的形式,描述一些常见的问题。如果希望详细理解相关内容,也可以参考官方文档。
modules 机制在 go 里面的子命令是 go mod
。
modules 机制是 go 1.11 才引入的,所以开始用之前先检查下自己的 go 版本 go version
,建议使用最新的 1.13 版本,涵盖了 module 机制相关的较多更新和功能。
在保证 go 版本至少在 1.11 或以上之后,就要开启一下环境变量 GO111MODULE,启用 module 机制。
export GO111MODULE=on
或者设置为 auto 模式,这样在 GOPATH 路径下的项目可以不使用 module 机制。
export GO111MODULE=auto
建议加到 ~/.bashrc
、~/.zshrc
等配置中启动便自动生效。
如果您的项目之前已经用 modules 管理了,那么到此为止你本地的环境已经完成初始化了。
如果项目里之前没有使用 modules,切换过来也很简单,删除原先的 vendor
文件夹(保险起见可以移动到项目之外的地方),在项目里执行一下初始化命令即可。
go mod init [module名称]
包名跟以前一样,还是跟 go path 强关联的,比如我们的项目一般是在 http://github.com/oam-dev/oam-go-sdk
,那么你的包名就是这个了。
go mod init github.com/oam-dev/oam-go-sdk
初始化完成后就会看见项目里有个 go.mod
文件。
然后通过 go mod download
就可以下载所有原先 vendor
中的依赖。
<a name="2eee5f31"></a>
使用了 go module
以后,你的许多命令就会与包管理集成,比如 go get
、go build
、go run
都会自动查找并在go.mod
里面更新依赖。
所以按照 Go 官方团队的意思,一般情况下,你根本不用关心包管理的问题了。( 当然,这真的纯粹只是官方在 YY )
所以到这里你就已经学会 go modules
了,没超过5分钟吧?
实际因为 go 官方对包管理重视的太晚,各种包都没有版本的概念,随随便便就会出现各种冲突,而且由于 go modules 实在是太自动了,所以就算你学会了怎么用 modules,最后还是会比较头疼。
下面我们就以 FAQ 的形式回答项目中遇到各种问题怎么办。
Go module 加入了代理的机制,只要设置一个代理地址,就可以提供代理访问。阿里云就提供了这样一个 go 的代理 ,是完全免费的服务。公共代理仓库会代理并缓存go模块,你可以利用该代理来避免 DNS 污染或其他问题导致的模块拉取缓慢或失败的问题,加速你的项目构建。
设置的方式非常简单,只需要设置如下环境变量即可,执行命令:
export GOPROXY=https://mirrors.aliyun.com/goproxy/
go1.13 加入了 mirror 机制,可以通过 go env -w
设置 mirror,其实就是之前的 GOPROXY 做的更到位一些,执行命令:
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct
逗号后面可以增加多个 proxy,最后的 direct 则是在所有 proxy 都找不到的时候,直接访问,代理访问不到的私有仓库就可以正常使用了。
这个功能基本上是在家远程办公的必备工具了。
这个几乎是最常见的问题,比较简单的解决方案是 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
了。
方案一:上述方式通过修改 git config
,却依赖你本地的 ~/.ssh/id_rsa
,在构建时可以通过 multistage-build 把私钥 add 到 stage 0
里面 build,然后用后面新的 stage 生成镜像,这样构建的镜像就不会包含私钥;
方案二: 更为安全的方式是,在每次构建 Docker 镜像之前,先在本地用 go mod vendor
把包缓存下来,在 Dockerfile 构建镜像过程中还是用 GOPATH 和 Vendor 机制来管理依赖。。
先查看版本:
$ 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
go 的依赖与项目名直接相关,这就导致如果我们使用了 github 上的项目,然后项目的维护人员突发奇想改个项目名称,就会导致所有依赖它的项目都无法找到依赖。
还好有 replace 的机制:
replace golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a => github.com/golang/crypto v0.0.0-20190313024323-a1f597ede03a
这就要梳理版本了,是最没有捷径的。一个比较简单的办法是把所有 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 ...
左边是项目包,右边是被依赖的包和版本。
如果确实存在两个需要指定版本的包互相冲突,那就要做取舍,修改代码,升级或降级某个包了。
如果在代码调试过程中,涉及到修改其他依赖项目代码,这时候就要引用本地包,也可以采用 replace 机制:
require ( golang.org/x/crypto v0.0.0 ) replace golang.org/x/crypto v0.0.0 => ../crypto
后面这个就是个相对项目路径的本地依赖所在路径。
解决了上面的这些问题,基本上你就可以愉快的使用 module 功能啦。
go mod 里还有一些其他功能,也在此列举,方便大家查阅:
OAM(Open Application Model)开放应用模型是阿里联合微软针对云原生应用的模型,第一次对“以应用为中心”的基础设施和构建规范进行了完整的阐述。应用管理者只要遵守这个规范,就可以编写出一个自包含、自描述的“应用定义文件”。
OAM 将应用划分为应用组件和应用特征两部分,应用组件是应用本身的逻辑,而应用特征则是云上的各种通用能力(如扩缩容、监控、灰度等等),大大提升了应用构建时模块化复用能力,将云上的各类资源和能力都转化为了标准化的可“声明”对象。
同时 OAM 强调关注点分离,通过标准化的模型将应用开发不同阶段的 API 进行分层,流程上先由研发定义应用组件,再由运维配置云上的各种策略,最后由基础设施团队统一提供各类模块化的能力。OAM 则在其中起着彼此协作的粘合剂作用,大大提高了应用交付的效率。
O
关于如何学会使用 go modules问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。