Go语言依赖管理

早期的Go语言被很多开发者所吐槽的一个问题就是没有依赖包的管理,不过随着版本的不断更迭,Go语言依赖管理方面也在不断的完善。

为什么需要依赖管理

最初的时候Go语言所依赖的所有的第三方包都放在 GOPATH 目录下面,这就导致了同一个包只能保存一个版本的代码,如果不同的项目依赖同一个第三方的包的不同版本,应该怎么解决呢?

godep

godep 是一个Go语言官方提供的通过 vender 模式来管理第三方依赖的工具,类似的还有由社区维护的准官方包管理工具 dep。

Go语言从 1.5 版本开始开始引入 vendor 模式,如果项目目录下有 vendor 目录,那么Go语言编译器会优先使用 vendor 内的包进行编译、测试等。

安装godep工具

我们可以通过go get 命令来获取 godep 工具。

go get github.com/tools/godep

命令执行成功后会将 godep 工具的源码下载到 GOPATH 的 src 目录下对应的文件夹中,同时还会在 GOPATH 的 bin 目录下生成一个名为 godep.exe 的可执行文件,如下图所示。

获取 godep 工具

为了方便使用 godep 工具,我们需要将存放 godep.exe 文件的目录添加到环境变量 PATH 中。在系统变量中找到并选中“Path”一行,点击“编辑”按钮,在新弹出的窗口中点击“新建”,然后在最下面一行中填入对应的目录信息。确认无误后点击“确定”。

将存放 godep 工具的目录添加的环境变量中

环境变量设置的打开方式我们在《安装Go语言开发包》一节中已经介绍过了,这里不再赘述。

godep工具的基本命令

完成上面的操作后,我们就可以在命令行窗口(CMD)中使用 godep 工具了,godep 支持的命令如下表所示:

命令 作用
godep save 将依赖包的信息保存到 Godeps.json 文件中
godep go 使用保存的依赖项运行 go 工具
godep get 下载并安装指定的包
godep path 打印依赖的 GOPATH 路径
godep restore 在 GOPATH 中拉取依赖的版本
godep update 更新选定的包或 go 版本
godep diff 显示当前和以前保存的依赖项集之间的差异
godep version 查看版本信息

使用godep help [命令名称]可以查看命令的帮助信息,如下所示。

C:\Users\Administrator>godep help go
Args: godep go [-v] [-d] command [arguments]

Go runs the go tool with a modified GOPATH giving access to
dependencies saved in Godeps.

Any go tool command can run this way, but "godep go get"
is unnecessary and has been disabled. Instead, use
"godep go install".

If -v is given, verbose output is enabled.

If -d is given, debug output is enabled (you probably don't want this, see -v).

使用godep工具

执行godep save 命令,会在当前目录中创建 Godeps 和 vender 两个文件夹。Godeps 文件夹下会生成一个 Godeps.json 文件,用来记录项目中所依赖的包信息;vender 目录则是用来保存当前项目所依赖的所有第三方包。

godep save 命令执行成功后生成的两个文件夹

生成的 Godeps.json 文件的结构如下所示:

{
    "ImportPath": "main",
    "GoVersion": "go1.13",
    "GodepVersion": "v80",
    "Deps": [
        {
            "ImportPath": "github.com/go-gomail/gomail",
            "Comment": "2.0.0-23-g81ebce5",
            "Rev": "81ebce5c23dfd25c6c67194b37d3dd3f338c98b1"
        }
    ]
}

其中,“ImportPath”为项目的路径信息,“GoVersion”为Go语言的版本号,“GodepVersion”为 godep 工具的版本号,“Deps”为当前依赖包的路径、版本号信息等等。

提示:当引用的第三方包要升级时,只需要修改 Godep.json 里面的依赖包的版本号,然后再次执行 godep save 命令即可。

godep 工具的主要功能就是控制Go语言程序编译时依赖包搜索路径的优先级。例如查找项目的某个依赖包,首先会在项目根目录下的 vender 文件夹中查找,如果没有找到就会去 GOAPTH/src 目录下查找。

go module

go module 是Go语言从 1.11 版本之后官方推出的版本管理工具,并且从 Go1.13 版本开始,go module 成为了Go语言默认的依赖管理工具。

GO111MODULE

在Go语言 1.12 版本之前,要启用 go module 工具首先要设置环境变量 GO111MODULE,不过在Go语言 1.13 及以后的版本则不再需要设置环境变量。通过 GO111MODULE 可以开启或关闭 go module 工具。
  • GO111MODULE=off 禁用 go module,编译时会从 GOPATH 和 vendor 文件夹中查找包。
  • GO111MODULE=on 启用 go module,编译时会忽略 GOPATH 和 vendor 文件夹,只根据 go.mod 下载依赖。
  • GO111MODULE=auto(默认值),当项目在 GOPATH/src 目录之外,并且项目根目录有 go.mod 文件时,开启 go module。

Windows 下开启 GO111MODULE 的命令为:

set GO111MODULE=on 或者 set GO111MODULE=auto

MacOS 或者 Linux 下开启 GO111MODULE 的命令为:

export GO111MODULE=on 或者 export GO111MODULE=auto

在开启 GO111MODULE 之后就可以使用 go module 工具了,也就是说在以后的开发中就没有必要在 GOPATH 中创建项目了,并且还能够很好的管理项目依赖的第三方包信息。

使用 go module 的go mod init 命令后会在当前目录下生成一个 go. mod 文件,并且在编译/运行当前目录下代码或者使用go get 命令的时候会在当前目录下生成一个 go.sun 文件。

使用 go mod init 命令生成的两个文件

go.mod 文件记录了项目所有的依赖信息,其结构大致如下:

module main.go

go 1.13

require (
    github.com/astaxie/beego v1.12.0
    github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect
)

其中,module 为 go.mod 文件所属的包,require 为项目所依赖的包及版本号,indirect 表示间接引用。

go.sum 文件则是用来记录每个依赖包的版本及哈希值,如下所示。

github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/OwnLocal/goes v1.0.0/go.mod h1:8rIFjBGTue3lCU0wplczcUgt9Gxgrkkrw7etMIcn8TM=
github.com/astaxie/beego v1.12.0 h1:MRhVoeeye5N+Flul5PoVfD9CslfdoH+xqC/xvSQ5u2Y=
github.com/astaxie/beego v1.12.0/go.mod h1:fysx+LZNZKnvh4GED/xND7jWtjCR6HzydR2Hh2Im57o=

常用的 go mod 命令如下表所示:

命令 作用
go mod download 下载依赖包到本地(默认为 GOPATH/pkg/mod 目录)
go mod edit 编辑 go.mod 文件
go mod graph 打印模块依赖图
go mod init 初始化当前文件夹,创建 go.mod 文件
go mod tidy 增加缺少的包,删除无用的包
go mod vendor 将依赖复制到 vendor 目录下
go mod verify 校验依赖
go mod why 解释为什么需要依赖

GOPROXY

proxy 顾名思义就是代理服务器的意思。大家都知道,国内的网络有防火墙的存在,这导致有些Go语言的第三方包我们无法直接通过go get 命令获取。GOPROXY 是Go语言官方提供的一种通过中间代理商来为用户提供包下载服务的方式。要使用 GOPROXY 只需要设置环境变量 GOPROXY 即可。

目前公开的代理服务器的地址有:
  • goproxy.io
  • goproxy.cn:(推荐)由国内的七牛云提供。

Windows 下设置 GOPROXY 的命令为:

go env -w GOPROXY=https://goproxy.cn,direct

MacOS 或 Linux 下设置 GOPROXY 的命令为:

export GOPROXY=https://goproxy.cn

Go语言在 1.13 版本之后 GOPROXY 默认值为 https://proxy.golang.org,在国内可能会存在下载慢或者无法访问的情况,所以十分建议大家将 GOPROXY 设置为国内的 goproxy.cn。

使用go get命令下载指定版本的依赖包

执行go get 命令,在下载依赖包的同时还可以指定依赖包的版本。
  • 运行go get -u命令会将项目中的包升级到最新的次要版本或者修订版本;
  • 运行go get -u=patch命令会将项目中的包升级到最新的修订版本;
  • 运行go get [包名]@[版本号]命令会下载对应包的指定版本或者将对应包升级到指定的版本。

提示:go get [包名]@[版本号]命令中版本号可以是 x.y.z 的形式,例如 go get foo@v1.2.3,也可以是 git 上的分支或 tag,例如 go get foo@master,还可以是 git 提交时的哈希值,例如 go get foo@e3702bed2。


推荐文章
Python是什么

Python是一种面向对象的、交互式的、解释型编程语言。Python支持面向对象的程序设计,源程序不需要编译即可在Python运行环境中互动式地运行。 Python已经具有近二十年的发展历史,成熟且

addOrder(Orderorder) order:为Order对象的示例,可以通过Order类的desc方法(降序方法)和asc方法(升序方法)指定等排序方式。 示例 Sessionses

7个开放式的Web开发人员面试题(附回答策略)

Web开发人员的职责是什么?解析:Web工程师应该充分了解自己的角色,以及怎样为Web设计和开发做出贡献。这个问题能帮助面试官了解求职者打算怎样配合团队,以及他们是否知道自己要做些什么。面试官想知道什

Python推导式(列表推导式、元组推导式、字典推导式和集合推导式)详解

推导式(又称解析器),是Python独有的一种特性。使用推导式可以快速生成列表、元组、字典以及集合类型的数据,因此推导式又可细分为列表推导式、元组推导式、字典推导式以及集合推导式。 Python列表

Android BackupAgentHelper实现数据备份与恢复

上一节教程我们学习了怎么使用BackupAgent实现Android数据备份与恢复,这一节我们主要介绍如何使用BackupAgentHelper实现Android数据备份与恢复。 1)实现Backu

零基础汇编语言入门教程(魔鬼作坊VIP共26课全)

解决问题万能思路:遇到不懂的问题,都可以百度谷歌一下,你就知道了。因为你想解决的问题,别人可能早已解决。 我们在VIP零基础绝密汇编语言入门课程相会了,那么,先来看看学习汇编语言的15大好处:

PHP preg_filter():执行一个正则表达式的搜索和替换

PHPpreg_filter()函数也用于执行一个正则表达式的搜索和替换,等价于我们前面介绍的《preg_replace()函数》,不同的是preg_filter()函数只返回匹配成功的结果,而 pr

云计算是对什么技术的发展和应用?

云计算是对并行计算、网格计算、分布式计算技术的发展和应用。云计算(cloudcomputing)是分布式计算的一种,指的是通过网络“云”将巨大的数据计算处理程序分解成无数个小程序,然后,通过多部服务器

什么是sap管理系统?

SAP系统(systemsapplicationsandproductsindataprocessing)是一套企业资源管理软件系统,具有现代化、信息化、智能化的应用优势,能够为企业管理问题的解决提供

优先使用函数对象自定义STL算法规则

作为一门面向对象的编程语言,使用C++编写程序有一个缺点,即随着代码面向对象程度的提高,其执行效率反而会降低。例如,经实验证明几乎在所有情况下,直接操作一个double类型变量的执行效率,要比操作一个

Python Event实现线程通信

Event是一种非常简单的线程通信机制,一个线程发出一个Event,另一个线程可通过该Event被触发。 Event本身管理一个内部旗标,程序可以通过Event的set()方法将该旗标设置为True

Java使用foreach循环遍历Collection集合

《JavaIterator遍历Collection集合元素》一节中主要讲解如何使用Iterator接口迭代访问Collection集合里的元素,除了这个方法之外,我们还可以使用Java5提供的fore

磁盘清理会误删东西吗?

磁盘清理不会误删东西。磁盘清理只是清理系统中的无用文件,如系统缓存、IE缓存、和某些直接从网上下载下来安装的程序;它是不会误删除系统文件的。扩展资料:磁盘碎片整理可以提高文件的读写速度,可是盲目地进行

Hibernate HQL的5种常见检索方式详解

在Hibernate核心API中,Query接口是专门用于HQL查询的接口。教程《Hibernate核心接口》已经讲解过该接口,并通过案例演示了该接口中list()方法的使用。本节将针对HQL中其他几

Java main()方法的格式为什么是固定不变的?

在《Javamain()方法》一节中提到main()方法定义必须是“publicstaticvoidmain(String[]字符串数组参数名)”,本节告诉大家为什么在Java中定义main方法的语法

深度学习在移动端的应用

本节将介绍一些用于移动端深度学习的实例。它的学习情况与桌面学习或云端深度学习完全不同(在这两种学习中,GPU和电力通常是可利用的)。实际上,在移动设备上,节省电量和减少GPU的使用是非常重要的。 无

Servlet客户端跳转

Servlet packagech05; importjava.io.IOException; importjava.io.PrintWriter; importjavax.servlet.S

jQuery removeAttr()方法删除属性

在jQuery中,我们可以使用removeAttr()方法来删除元素的某个属性。 语法: $().removeAttr("属性名") 举例: .content{col

JSP out对象:向客户端输出数据

out对象是一个输出流,用来向客户端输出数据,可以是各种数据类型的内容,同时,它还可以管理应用服务器上的输出缓冲区,缓冲区的默认值是8KB,可以通过页面指令page来改变默认大小。 out对象是一个

Python第三方库(模块)下载和安装(使用pip命令)

进行Python程序开发时,除了使用Python内置的标准模块以及我们自定义的模块之外,还有很多第三方模块可以使用,这些第三方模块可以借助Python官方提供的查找包页面(https://pypi.o