五分钟学会使用 go modules(含在家办公使用技巧)

导读go modules是 golang 1.11 新加的特性。现在 1.13 都已经发布了第 7 个小版本了,几乎全部大项目均已开始使用,这天然也包括 Kubernetes 生态中的众多项目。笔者在开发 OAM 相关项目的时候,却发现 modules 的各项功能看似简单,却并无那么好用,因而便想给你们分享一下使用心得,但愿你们也能在最短期内学会 modules 的使用,避免踩坑。git

modules 是什么?

简单说就是包管理,Golang 的包管理素来以混乱著称,之前是依赖 $GOPATH,只要你的代码放在指定路径下就行了,彻底没有“包管理”的概念。被社区吐槽了好久之后开始搞vendor机制,简单来讲就是代码不光是能够放到指定路径,还能够放在项目自身路径的 vendor 文件夹。这个解决的问题是:你引用的代码包上游变动不会直接影响你的项目,这显然是开始关心“包版本”了。遗憾的是依旧没有解决包管理的问题,好比不一样的包依赖了同一个包的不一样版本怎么办?版本间代码冲突怎么办?vendor机制并无解决,因而围绕vendor/社区就出了几十个包管理工具,一时间百花齐放、百家争鸣、各有所长,致使 golang 的包管理生态变得有些混乱。对这段历史感兴趣的能够阅读下笔者曾经写的文章《Go 包管理的前世此生》github

更有意思的是,在 go 官方社区看到包管理工具的乱象后,也作了个功能相似的工具dep,原理与其余各种依靠vendor/机制的包管理工具相似,准备对包管理作统一。当你们对 dep 工具报以指望并纷纷开始切换到 dep 工具管理依赖包的时候,go 官方又发布了如今的 modules 机制,彻底放弃了以前的 dep 工具与 vendor 机制。这样的操做在社区引发了巨大的争议,modules 与 go getgo build 等官方工具生态有很好的集成,官方的意图天然是但愿抛开原有的历史包袱,经过全新的方式拯救世界。然而实际体验下来,却依旧不尽如人意。golang

总的来讲大趋势已是用modules,go1.13 也对 modules 机制作了很多工做。docker

言归正传,本文的目标是但愿能用 5~10 分钟时间带您学会使用 go modules,而后经过 QA 的形式,描述一些常见的问题。若是但愿详细理解相关内容,也能够参考官方文档api

初始化

modules 机制在 go 里面的子命令是go mod缓存

modules 机制是 go 1.11 才引入的,因此开始用以前先检查下本身的 go 版本go version,建议使用最新的1.13 版本,涵盖了 module 机制相关的较多更新和功能。安全

在保证 go 版本至少在 1.11 或以上以后,就要开启一下环境变量GO111MODULE,启用 module 机制。bash

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 中的依赖。

平常包管理

使用了go module之后,你的许多命令就会与包管理集成,好比go getgo buildgo run都会自动查找并在go.mod里面更新依赖。

因此按照 Go 官方团队的意思,通常状况下,你根本不用关心包管理的问题了。( 固然,这真的纯粹只是官方在 YY )

因此到这里你就已经学会go modules了,没超过5分钟吧?

FAQ

实际由于 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 都找不到的时候,直接访问,代理访问不到的私有仓库就能够正常使用了。

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

公司经过 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了。

Dockerfile 中构建镜像怎么解决私有库的依赖包问题?

  • 方案一:上述方式经过修改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 命令一览

go mod 里还有一些其余功能,也在此列举,方便你们查阅:

1.png

最后

OAM(Open Application Model)开放应用模型是阿里联合微软针对云原生应用的模型,第一次对“以应用为中心”的基础设施和构建规范进行了完整的阐述。应用管理者只要遵照这个规范,就能够编写出一个自包含、自描述的“应用定义文件”。

OAM 将应用划分为应用组件和应用特征两部分,应用组件是应用自己的逻辑,而应用特征则是云上的各类通用能力(如扩缩容、监控、灰度等等),大大提高了应用构建时模块化复用能力,将云上的各种资源和能力都转化为了标准化的可“声明”对象。

同时 OAM 强调关注点分离,经过标准化的模型将应用开发不一样阶段的 API 进行分层,流程上先由研发定义应用组件,再由运维配置云上的各类策略,最后由基础设施团队统一提供各种模块化的能力。OAM 则在其中起着彼此协做的粘合剂做用,大大提升了应用交付的效率。

OAM 相关内容在 github 上彻底开源,同时咱们也为 Go 生态编写了oam-go-sdk方便快速实现 OAM。

目前,阿里巴巴团队正在上游贡献和维护这套技术,若是你们有什么问题或者反馈,也很是欢迎与咱们在上游或者钉钉联系。

查看更多:https://yq.aliyun.com/article..._content=g_1000104490

上云就看云栖号:更多云资讯,上云案例,最佳实践,产品入门,访问:https://yqh.aliyun.com/

相关文章
相关标签/搜索