Go Module 依赖管理

这世上太多的人,宁愿吃生活苦,也不愿吃自律的苦。大概是因为生活的苦,躺着就来了,而自律的苦,得自己去找。

go module 也一直在不断迭代的路上,是否还记得 glide 这个包管理工具,在没有 go module 之前,我们项目就一直在使用 glide 做包管理。

后来,开始使用 vendor 的模式,go mod init 初始化 go.mod 文件,go getgo mod tidy 等等一顿操作。总的来说,go mod 越来越好用了。再后来,听工作中的同事说起来,现在都不流行用 vendor 目录了,都直接使用 gopath 路径了。

我兴致勃勃地去把项目下的 vendor 目录删除掉,果然,程序依旧可以正常执行。但程序正式部署的时候却无法编译通过。每家公司代码发布的模式总是各有特点,果然不能强求啊。另一方面,完全搞清楚这些东西,确实也不是强需求。

我也开始明白, vendor 只是可选的一种模式,项目下不使用 vendor 目录,同样可以正常运行。区别点在于 vendor 不需要重新下载依赖。就目前而言,有的项目在使用 vendor,有的项目没有使用 vendor,不能强求完全一致。

我们整理一下 go mod 的几个命令,就我们工作而言,搞清楚如何正确地使用这些命名获取才是最重要的。我经常使用的就是 go mod tidy 和 go mod vendor,基本每次需求变更都会使用。

各种各样的奇怪问题

包依赖管理已经成为编程语言必备的技能、PHP、Go、Java、Rust,每种语言都有对应的依赖管理模式。但开发过程中,经常会遇到奇奇怪怪的环境问题。

好在编程环境问题,基本是解决了之后就不会再遇到。但每次解决起来都挺痛苦的,比如,包的权限问题了、依赖的版本问题等等。

关键的几个环境变量

GOPRIVATE、GOPROXY、GONOPROXY 出现的频率最高,很多报错都是没有正确配置这几个环境变量导致的。GOPRIVATE 指定的包不需要通过 GOPROXY 代理进行抓取,尤其是指定了 GOPROXY 环境变量的时候。

export GOPROXY=https://goproxy.io,direct
export GOSUMDB=off

可以在系统环境中设置全局的环境变量,也可以单独为项目指定环境变量。

在这里插入图片描述

使用 ssh 来替代 https 授权

git 下载依赖库的时候有两种模式:https、ssh,对于内部的私有库来说,我们经常采用 ssh 的下载模式。如果在执行 go get 的过程中,出现授权之类的报错,可以尝试下面的处理方式:

git 可以配置使用 SSH 来替代 HTTPS 进行授权,只需要指定一个 URL 前缀就可以。一般来说,可以手动编辑家目录下的 ~/.gitconfig 文件,形如下面这样的内容:

[url "git@github.com:"]
        insteadof = https://github.com/

对应的命名行编辑模式如下,我经常会使用下面的命令,把其中的 github.com 修改为公司的私有仓库地址就 OK 了。

 git config --global url."git@github.com:".insteadOf "https://github.com/"

go mod 命令

官方文档有相关的介绍,地址是:Go Modules Reference,经常会有很多有用的小特性可以把玩。

go mod vendor

依赖管理采用的是 vendor 模式,会将 go.mod 中的依赖包存储到 vendor 目录中。如果项目下没有 vendor 目录,该命令也会创建一个 vendor 目录。

每次我们通过 go get 下载到一个依赖包之后,我们还需要执行 go mod vendor 将依赖包复制到 vendor 目录中,只有这样,我们实际的代码才是生效的。

比如,你要获取一个新的依赖版本,你虽然通过 go get xxx@v2 获取到了依赖,但这个操作只是更新了你的 go.mod 文件,实际的 vendor 目录下还是原来的版本,我们需要执行 go mod vendor 才能让新版本生效。

在本地调试功能时,为了方便,经常会有人手动编辑 vendor 下的依赖项目,执行 go mod vendor 也会重新将这些本地修改覆盖。

go mod tidy

go mod tidy ensures that the go.mod file matches the source code in the module. It adds any missing module requirements necessary to build the current module’s packages and dependencies, and it removes requirements on modules that don’t provide any relevant packages. It also adds any missing entries to go.sum and removes unnecessary entries.

用来对项目依赖做整理,可能会增加/减少项目的依赖,这个命名本身是无害的,提交代码之前执行一下,代码会变得更让人放心。

有时候可能会迷惑,go mod tidy 和 go mod vendor 的执行顺序,按它们的功能介绍,go mod tidy 应该优先被执行

go clean -modcache

这个命名很少用,但不影响我们经常遇到各种奇奇怪怪的依赖问题,实在是找不出哪里出问题了,就试试执行一下这个命名。

你有没有想过这个问题:使用 go get 下载的依赖都存储到哪里了?而这个命令就是用来清除些 go get 下载下来的依赖库。

go 提供了一个环境变量,可以手动指定 modcache 的路径:GOMODCACHE。在命令行执行 go env ,就可以查看这个路径。

go mod why

go mod why [-m] [-vendor] packages...

我们执行 go mod tidy 时,控制台输出了莫名其妙的报错提示,我们很抓狂,我们反复执行 go mod vendor / go mod tidy,甚至多次重启 ide 仍旧无济于事。

这个时候我们可能需要使用这个命名,搞清楚报错依赖的包的依赖图谱。但我发现,这个命名如果不加 -m 的子属性,就无法正常输出依赖关系信息。-m 子属性的作用是什么呢?

在这里插入图片描述

The -m flag causes go mod why to treat its arguments as a list of modules. go mod why will print a path to any package in each of the modules. Note that even when -m is used, go mod why queries the package graph, not the module graph printed by go mod graph.

😄 原来如此,如果不加 -m 属性的话,命令只会查找当前主项目的依赖,而不会查找依赖包的依赖。不管怎么说,加 -m 的子属性肯定是没有问题的。

go list

当想查看依赖包的版本时,这个命名可能会有用。我经常会想看看依赖包现在都提供了哪些版本,这个包就可以帮我们列出来。经常被拿来举例的命名:go list -m -versions,我自己的体验是,这个命名不是那么好用。

在这里插入图片描述

GO111MODULE

Go 1.1包含了对Go Modules预支持,包括调整后的go get命令。后续版本总GOPATH和老的go get可能会被官方移除。

Go Modules中支持了一个临时环境变量:GO111MODULE,可以赋值为offonauto

  1. 值为off,表示不支持Go Modules模式,Go仍然在vendorGoPATH路径下查找依赖;
  2. 值为on,表示当前明确使用Go ModulesGo不再去GOPATH下查找任何依赖;
  3. 值为auto或未设置,表示是否启用Go Modules依赖当前的目录情况,当编译的项目在GoPATH/src之外,或者当前目录或子目录本身包含go.mod文件,则启用Go Modules模式。

Defining a module

module通过源码根目录下的go.mod文件来定义。根路径下的module是项目依赖包的集合,但会排除子目录的go.mod文件。

下面是go mod文件模版:

module example.com/m

require (
    golang.org/x/text v0.3.0
    gopkg.in/yaml.v2 v2.1.0
)

要开始使用go mod,仅需要在项目下执行go mod init命令创建go.mod文件即可。

go mod init example.com/m

Modules and vendoring

当使用module时,Go命令会完全忽略vendor目录。为了跟之前Go的依赖管理相兼容,我们可以使用go mod vendor 创建vendor目录来存储编译代码的依赖包。如果在编译的时候要使用vendor中的依赖包,需要使用go build -mod=vendor命令。

go mod vendor 
go build -mod=vendor

Go Get

The -u flag instructs get to use the network to update the named packages and their dependencies. By default, get uses the network to check out missing packages but does not use it to look for updates to existing packages.

首先,go get解析需要新增哪些依赖。可以通过在包名后添加@version或者@branch等方式来取代命令的默认更新行为。如果后缀指定为@none,则表明该依赖应该被移除。

其次,go get会下载、编译、安装指定的包。包的安装模式也是被允许的,比如使用go get golang.org/x/perf/cmd/..来更新cmd下的所有子包。

go get -u <repo url>
go mod vendor

熟悉govendor的肯能会有一种熟悉的感觉,这不就是govendor add +e吗?

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值