前言

最近在看一些go语言相关的书,发现了一个有意思的事情:其中一本书最新印刷的版本是2017年3月,而golang包管理的后起之秀go module伴随go1.11于2018年8月诞生——因此,书里没有。

有感于golang发展速度之快,且当下项目中go modulego vendor(go1.5之后一个热门的包管理工具)交织,甚至时不时看到go path包管理模式在一些文章中死灰复燃,我想有必要正确梳理一下其中的缘由,以便大家选择合适的包管理模式。

白泽,无脑选择go module不好吗?过时的东西有必要学吗?

事实上,我认为你可以不用它,但是你得懂为什么这种技术不推荐甚至被弃用,而且你很难定义什么是过时的技术,比如我项目中就用到了vendor。很多golang学习者可能有其他语言的基础,上手go也很快,java有maven,那go必然也有xx包管理工具吧!打开搜索引擎输入go快速入门,安装与项目构建,有的人查到了go path,有的人查到了govendor、有的人则是go module

这也是我想写一篇文章总结的原因(万一有一天go module也不推荐使用了呢!这种演变的思路值得了解),看过之后保证你能看懂别人文章中写的GOPATH/src、GOPATH/bin、GOPATH/pkg/mod云云,我们开始。

两个命令

go install xxx(下载xxx第三方二进制可执行文件

go get xxx(下载xxx第三方依赖包

下载可执行文件/第三方依赖到本地哪里?不同的包管理工具不同,下面讲。

两个路径

  • GOROOT:go的安装目录,类似java的jdk,存放一些内置的开发包和工具。
  • GOPATH:go指定的工作空间,用于保存go项目的代码和第三方依赖包。
# mac可以通过go env查看go相关的环境变量,windows类似
go env
GOROOT="/usr/local/go"
GOPATH="/Users/baize/GolandProjects/"

三个包管理工具

go path【不推荐使用】

go path是最早的依赖包管理方式(Go1.0),启用GOPATH模式(注意区分GOPATH模式和GOPATH路径,这是两个语境),要求将所有工程代码要求放在GOPATH/src目录下。在工程经过 go build xxxgo install xxx go get xxx等指令后,会将拉取的第三方xxx依赖包放在GOPATH/src目录下,产生的二进制可执行文件放在 GOPATH/bin 目录下,生成的中间缓存文件会被保存在 GOPATH/pkg 下。

问题:GOPATH模式下没有版本控制的概念,在执行 go get 的时候,获取的永远是最新的依赖包,下载到GOPATH/src,如果你有两个工程依赖一个包的v1和v2版本,则会发生冲突,因为 GOPATH 模式下两个工程内依赖的导入路径都是一样的,因此两个工程获取的都是v2版本。

命令:显然GOPATH模式下go get会将代码拉取到GOPATH/src,这个模式已经不推荐使用了。

govendor【不推荐使用】

在 Go 1.5版本之后,Go 提供了 GO15VENDOREXPERIMENT 环境变量(Go 1.6版本默认开启该环境变量)和 Govendor 包管理工具,用于将 go build 时的应用路径搜索调整成为当前工程/vendor 目录的方式,有效的解决了不同工程使用自己独立的依赖包目录。编译 Go 代码会优先从vendor目录先寻找依赖包,vendor目录如果没有找到,然后在 GOPATH 中查找,都没找到最后在 GOROOT 中查找。

优势:因为将第三方依赖完全和工程整合,使得项目构建速度快,且可以工作在无法连接外网的CI/CD流程中。

问题:放弃了依赖重用,使得冗余度上升

下载:go install github.com/kardianos/govendor(govendor是第三方可执行文件,下载可执行文件用go install,用go get也行,但是会有告警)。

命令:govendor --help查看所有命令(要先使用go get xxx将xxx依赖下载到$GOPATH/src中,此时go vendor包管理本质是基于GOPATH模式的)

命令 功能
govendor init 初始化vendor目录
govendor add 添加包到vendor目录(相关依赖则是从$GOPATH/src中获取)
govendor add +external 添加所有外部包到vendor目录
govendor get 拉取依赖包vendor目录

然后我在govendor的代码库中看到了下面这段话:(这个README还是两年前更新的,而且这个库已经很久不维护了,嗯...)。

go module

从Go1.11开始,官方推出Go module作为包管理工具,且从Go1.13开始为默认选择启用。GOMODULE模式下所有依赖的包存放在GOPATH/pkg/mod目录下,所有第三方二进制可执行文件放在GOPATH/bin目录下,且工程项目可以放在GOPATH路径之外,但要求项目中需要有go.mod文件(该文件通过go mod init命令初始化可以得到)。

GOMODULE模式和GOPATH模式一样都指定了依赖包存放的位置,而不是如vendor模式放入工程内,区别在于GOMODULE的go.mod文件中记录了所依赖包的具体版本,既实现了工程之间重用依赖包,且解决了GOPATH模式下不同工程无法依赖同一个包的不同版本的问题。

启用GOPATH模式要求工程目录在GOPATH/src之下,而要使用GO MODULE模式,需要先开启配置。在Go1.13之后,可以通过如下命令设置GO MODULE启用状态。

mac:(windows类似)

# 光开启也是不行的,需要配合go.mod才能工作,下面讲
export GO111MODULE=on
export GO111MODULE=off
# 当项目路径在 $GOPATH 目录外部时, 设置为 GO111MODULE = on 当项目路径位于 GOPATH 内部时,即使存在 go.mod, 设置为 GO111MODULE = off
export GO111MODULE=auto

go mod命令:go help mod查看相关帮助命令(govendor是第三方可执行文件,但是go mod命令是go自带的,不用额外go install)

命令 功能
go mod init 初始化当前文件夹,创建go.mod文件,事实上,如果你的环境中GO111MODULE=on,使用类似goland的工具创建工程会自动生成go.mod
go mod tidy 包整理(多的删去、少的拉取),使用之前自然是import了需要的库了
go mod vendor 将依赖包复制到工程文件的vendor目录下

GO111MODULE=on且项目中包含go.mod文件时,执行go get xxx 或 go install xxx下载的或者二进制可执行文件将放入GOPATH/pkg/mod目录和GOPATH/bin目录下。

go mod vendor:

这里着重再提一下go mod vendor,刚刚还说govendor自己都不推荐用了,为什么GOMODULE模式还提供了这个关联go vendor功能的命令呢?

事实上,如果你需要使用vendor模式管理包,说明一定属于如下两种情况:

  1. 工作在GOPATH模式下,Go版本早于1.11或者GO111MODULE=off(因为这种方式依赖GOPATH模式,所以已经不推荐了)
  2. 工作在GO MODULE模式下,但是还是利用vendor管理依赖包,而go mod vendor就属于这种情况(算是保留了vendor一线生机,毕竟还是有使用场景的,且go mod vendor利用GOMODULE模式为基础,摒弃了GOPATH为基础的govendor)。

结束语

码字不易,三连才是真情~

刚建了个微信小群,欢迎加入一起唠嗑,一同备战秋招!

go包管理速通,一篇文章就够了,再也不用担心因为不会导包被辞退的更多相关文章

  1. Android:学习AIDL,这一篇文章就够了(下)

    前言 上一篇博文介绍了关于AIDL是什么,为什么我们需要AIDL,AIDL的语法以及如何使用AIDL等方面的知识,这一篇博文将顺着上一篇的思路往下走,接着介绍关于AIDL的一些更加深入的知识.强烈建议 ...

  2. (转载)Android:学习AIDL,这一篇文章就够了(下)

    前言 上一篇博文介绍了关于AIDL是什么,为什么我们需要AIDL,AIDL的语法以及如何使用AIDL等方面的知识,这一篇博文将顺着上一篇的思路往下走,接着介绍关于AIDL的一些更加深入的知识.强烈建议 ...

  3. (转载)Android:学习AIDL,这一篇文章就够了(上)

    前言 在决定用这个标题之前甚是忐忑,主要是担心自己对AIDL的理解不够深入,到时候大家看了之后说——你这是什么玩意儿,就这么点东西就敢说够了?简直是坐井观天不知所谓——那样就很尴尬了.不过又转念一想, ...

  4. 面试题-关于Java线程池一篇文章就够了

    在Java面试中,线程池相关知识,虽不能说是必问提,但出现的频次也是非常高的.同时又鉴于公众号"程序新视界"的读者后台留言让写一篇关于Java线程池的文章,于是就有本篇内容,本篇将 ...

  5. (转) TensorFlow深度学习,一篇文章就够了

    TensorFlow深度学习,一篇文章就够了 2016/09/22 · IT技术 · TensorFlow, 深度学习 分享到:6   原文出处: 我爱计算机 (@tobe迪豪 )    作者: 陈迪 ...

  6. Android:学习AIDL,这一篇文章就够了(上)

    前言 在决定用这个标题之前甚是忐忑,主要是担心自己对AIDL的理解不够深入,到时候大家看了之后说——你这是什么玩意儿,就这么点东西就敢说够了?简直是坐井观天不知所谓——那样就很尴尬了.不过又转念一想, ...

  7. 真的,Kafka 入门一篇文章就够了

    初识 Kafka 什么是 Kafka Kafka 是由 Linkedin 公司开发的,它是一个分布式的,支持多分区.多副本,基于 Zookeeper 的分布式消息流平台,它同时也是一款开源的基于发布订 ...

  8. TensorFlow深度学习,一篇文章就够了

    http://blog.jobbole.com/105602/ 作者: 陈迪豪,就职小米科技,深度学习工程师,TensorFlow代码提交者. TensorFlow深度学习框架 Google不仅是大数 ...

  9. Kafka 【入门一篇文章就够了】

    初识 Kafka 什么是 kafka Kafka 是由 Linkedin 公司开发的,它是一个分布式的,支持多分区.多副本,基于 Zookeeper 的分布式消息流平台,它同时也是一款开源的基于发布订 ...

随机推荐

  1. [BUUCTF]REVERSE——[2019红帽杯]easyRE

    [2019红帽杯]easyRE 附件 步骤: ida载入,没有main函数,就先检索了程序里的字符串 发现了base64加密的特征字符串,双击you found me跟进,找到了调用它的函数,函数很长 ...

  2. 例外日期(Project)

    <Project2016 企业项目管理实践>张会斌 董方好 编著 日历无论怎么样自定义,只要仍是存在固化规律的,就铁定会坏事,因为人类的历史就是在大规律中掺杂着无数无规律,再由无数无规律凝 ...

  3. CF127A Wasted Time 题解

    Content 平面上有 \(A_1(x_1,y_1),A_2(x_2,y_2),...,A_n(x_n,y_n)\) 共计 \(n\) 个点.你需要依次将 \(A_1\) 连接至 \(A_2\),\ ...

  4. CF984B Minesweeper 题解

    Content 有一个 \(n\times m\) 的扫雷地图,请判断这个地图是否合法,即对于所有格子,是否满足: 对应点的数字周围必须有对应数字个雷 空的地方周围没有雷 数据范围:\(1\leqsl ...

  5. 【九度OJ】题目1023:EXCEL排序 解题报告

    [九度OJ]题目1023:EXCEL排序 解题报告 标签(空格分隔): 九度OJ [LeetCode] http://ac.jobdu.com/problem.php?pid=1023 题目描述: E ...

  6. 【LeetCode】51. N-Queens 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 回溯法 日期 题目地址:https://leetco ...

  7. 【LeetCode】959. Regions Cut By Slashes 由斜杠划分区域(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题思路 代码 日期 题目地址:https://leetcod ...

  8. 【LeetCode】434. Number of Segments in a String 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 统计 正则表达式 字符串分割 日期 题目地址:htt ...

  9. 【LeetCode】47. Permutations II 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:递归 方法二:回溯法 日期 题目地址:htt ...

  10. Lotus and Horticulture

    Lotus and Horticulture Accepts: 91 Submissions: 641 Time Limit: 4000/2000 MS (Java/Others) Memory Li ...