教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 GO 依赖管理工具go Modules(官方推荐)

GO 依赖管理工具go Modules(官方推荐)

发布时间:2022-02-08   编辑:jiaochengji.com
教程集为您提供GO 依赖管理工具go Modules(官方推荐)等资源,欢迎您收藏本站,我们将为您提供最新的GO 依赖管理工具go Modules(官方推荐)资源

以前写过一篇关于go管理依赖包工具 dep的文章,当时认为dep将会成为官方依赖工具,现在看来是自己图样图斯内幕破了,正如官方一直提到dep是“official experiment”官方实验项目的那样,随着go modules 在go1.11版推出,go1.12版功能不断改进,再到go1.13版完善优化,正式扶正。预计dep将来也只能定格在“official experiment”了。

<h2>Go Modules有哪些特点:</h2> <ul><li>Go Modules是官方正式推出的包依赖管理项目,由Russ Cox (即Go 现在的掌舵人)推动,dep是“official experiment”仅此而已。</li> <li>Go modules 出现的目的之一就是为了解决 GOPATH 的问题,也就相当于是抛弃 GOPATH 了。以前项目必须在<code>$GOPATH/src</code> 里进行,现在Go 允许在<code> $GOPATH/src </code>外的任何目录下使用 go.mod 创建项目。当然现在</li> <li>随着模块一起推出的还有模块代理协议(Module proxy protocol),通过这个协议我们可以实现 Go 模块代理(Go module proxy),也就是依赖镜像。</li> <li>Tag必须遵循语义化版本控制,如果没有将忽略 Tag,然后根据你的 Commit 时间和哈希值再为你生成一个假定的符合语义化版本控制的版本号。</li> <li>Go modules 还默认认为,只要你的主版本号不变,那这个模块版本肯定就不包含 Breaking changes,因为语义化版本控制就是这么规定的啊。</li> <li>

Global Caching 这个主要是针对 Go modules 的全局缓存数据说明,如下:

<ul><li>同一个模块版本的数据只缓存一份,所有其他模块共享使用。</li> <li>目前所有模块版本数据均缓存在 <code>$GOPATH/pkg/mod</code>和 <code>$GOPATH/pkg/sum</code> 下,未来或将移至 <code>$GOCACHE/mod </code>和<code>$GOCACHE/sum</code> 下( 可能会在当 <code>$GOPATH</code> 被淘汰后)。</li> <li>可以使用 <code>go clean -modcache</code> 清理所有已缓存的模块版本数据。</li> </ul></li> </ul>

另外在 Go1.11 之后 GOCACHE 已经不允许设置为 off 了,我想着这也是为了模块数据缓存移动位置做准备,因此大家应该尽快做好适配。

如果你的版本是go1.12或更早版本,这里建议升级到go1.13,来体验一把go modules,看它能给你带来哪些方面身心的愉悦。

<h2>本文将介绍使用Go Modules相关操作</h2> <h3>1、安装Go 1.13或升级到Go 1.13</h3>

​ 安装

<h3>2、配置环境变量</h3> <pre><code>#修改 GOBIN 路径(可选) go env -w GOBIN=$HOME/bin #打开 Go modules go env -w GO111MODULE=on #设置 GOPROXY go env -w GOPROXY=https://goproxy.cn,direct</code></pre>

go env -w: Go1.13 新增了 <code>go env -w</code> 用于写入环境变量,而写入的地方是 <code>os.UserConfigDir</code> 所返回的路径,需要注意的是 <code>go env -w</code> 不会覆写。需要指出,它不会覆盖系统环境变量。

GO111MODULE:

这个环境变量主要是 Go modules 的开关,主要有以下参数:

<ul><li>auto:只在项目包含了 go.mod 文件时启用 Go modules,在 Go 1.13 中仍然是默认值,详见
:golang.org/issue/31857。</li> <li>on:无脑启用 Go modules,推荐设置,未来版本中的默认值,让 GOPATH 从此成为历史。</li> <li>off:禁用 Go modules。</li> </ul>

GOPROXY:

这个环境变量主要是用于设置 Go 模块代理,它的值是一个以英文逗号 “,” 分割的 Go module proxy 列表,默认是proxy.golang.org,国内访问不了。这里要感谢盛傲飞和七牛云为中国乃至全世界的 Go 语言开发者提供免费、可靠的、持续在线的且经过CDN加速Go module proxy(goproxy.cn)。

其实值列表中的 “direct” 为特殊指示符,用于指示 Go 回源到模块版本的源地址去抓取(比如 GitHub 等),当值列表中上一个 Go module proxy 返回 404 或 410 错误时,Go 自动尝试列表中的下一个,遇见 “direct” 时回源,遇见 EOF 时终止并抛出类似 “invalid version: unknown revision...” 的错误。

<h3>3、创建你的项目</h3>

这里我们在<code> $GOPATH/src </code>外,创建 /var/www/demo实例

<pre><code>mkdir /var/www/demo cd /var/www/demo</code></pre>

新建main.go

<pre><code>package main import ( "github.com/gin-gonic/gin" "fmt" ) func main() { r := gin.Default() r.GET("/ping", func(c *gin.Context) { fmt.Println("hello world!") c.JSON(200, gin.H{ "message": "pong", }) }) r.Run() // listen and serve on 0.0.0.0:8080 }</code></pre> <h3>4、在/var/www/demo根目录下</h3> <pre><code>#生成go.mod文件 go mod init demo</code></pre>

打开go.mod文件,内容

<pre><code>module demo go 1.13</code></pre>

go.mod 是启用了 Go moduels 的项目所必须的最重要的文件,它描述了当前项目(也就是当前模块)的元信息,每一行都以一个动词开头,目前有以下 5 个动词:

<ul><li>module:用于定义当前项目的模块路径。</li> <li>go:用于设置预期的 Go 版本。</li> <li>require:用于设置一个特定的模块版本。</li> <li>exclude:用于从使用中排除一个特定的模块版本。</li> <li>replace:用于将一个模块版本替换为另外一个模块版本。</li> </ul>

这里的填写格式基本为包引用路径 版本号,另外比较特殊的是 <code>go $version</code>,目前从 Go1.13 的代码里来看,还只是个标识作用,暂时未知未来是否有更大的作用。

<h3>5、在/var/www/demo根目录下,执行 go build</h3> <pre><code>go build</code></pre>

完成后项目

<pre><code>├── demo ├── go.mod ├── go.sum └── main.go</code></pre>

项目中增加了go.sum、demo文件

go.sum文件内容

<pre><code>github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI c5H38= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 h1:t8FVkw33L wilf2QiWkw0UV77qRpcH/JHPKGpKa2E8g= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod github.com/gin-gonic/gin v1.4.0 h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM LBO 5UPHJJDH72/q/3rZdM= ... </code></pre>

go.sum类似于比如 dep 的 Gopkg.lock 的一类文件,它详细罗列了当前项目直接或间接依赖的所有模块版本,并写明了那些模块版本的 SHA-256 哈希值以备 Go在今后的操作中保证项目所依赖的那些模块版本不会被篡改。

我们可以看到一个模块路径可能有如下两种:

<pre><code>github.com/gin-gonic/gin v1.4.0 h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM LBO 5UPHJJDH72/q/3rZdM=</code></pre>

前者为 Go modules 打包整个模块包文件 zip 后再进行 hash 值,而后者为针对 go.mod 的 hash 值。他们两者,要不就是同时存在,要不就是只存在 go.mod hash。

那什么情况下会不存在 zip hash 呢,就是当 Go 认为肯定用不到某个模块版本的时候就会省略它的 zip hash,就会出现不存在 zip hash,只存在 go.mod hash 的情况。

go.mod文件内容发生了变化,增加了

<pre><code>require github.com/gin-gonic/gin v1.4.0</code></pre>

默认使用最新版本的package。

<h3>更换依赖版本</h3>

查看gin所有历史版本

<pre><code>go list -m -versions github.com/gin-gonic/gin</code></pre>

github.com/gin-gonic/gin v1.1.1 v1.1.2 v1.1.3 v1.1.4 v1.3.0 v1.4.0

如果想更换依赖版本,比如v1.3.0,怎么办?

只需执行如下命令

<pre><code>go mod edit -require="github.com/gin-gonic/gin@v1.3.0" go tidy #更新现有依赖</code></pre>

@后跟版本号,这个时候go.mod已经修改好了

<pre><code>require github.com/gin-gonic/gin v1.3.0</code></pre>

查看所有项目依赖的包

<pre><code>go list -m all</code></pre> <pre><code>github.com/davecgh/go-spew v1.1.0 github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 github.com/gin-gonic/gin v1.4.0 github.com/golang/protobuf v1.3.1 github.com/json-iterator/go v1.1.6 github.com/mattn/go-isatty v0.0.7 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd github.com/modern-go/reflect2 v1.0.1 github.com/pmezard/go-difflib v1.0.0 github.com/stretchr/objx v0.1.0 github.com/stretchr/testify v1.3.0 github.com/ugorji/go v1.1.4 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 golang.org/x/text v0.3.0 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 gopkg.in/go-playground/assert.v1 v1.2.1 gopkg.in/go-playground/validator.v8 v8.18.2 gopkg.in/yaml.v2 v2.2.2</code></pre> <h3>注意</h3>

使用go.mod管理依赖会对go get命令产生一定影响,

<ul><li>用 <code>go help module-get</code> 和 <code>go help gopath-get</code>分别去了解 Go modules 启用和未启用两种状态下的 go get 的行为</li> <li>

用 <code>go get</code> 拉取新的依赖

<ul><li>拉取最新的版本(优先择取 tag):<code>go get golang.org/x/text@latest</code> </li> <li>拉取 <code>master</code> 分支的最新 commit:<code>go get golang.org/x/text@master</code> </li> <li>拉取 tag 为 v0.3.2 的 commit:<code>go get golang.org/x/text@v0.3.2</code> </li> <li>拉取 hash 为 342b231 的 commit,最终会被转换为 v0.3.2:<code>go get golang.org/x/text@342b2e</code> </li> <li>用 <code>go get -u</code> 更新现有的依赖</li> </ul></li> </ul><h3>快速迁移项目至 Go Modules</h3> <ol><li>在你项目的根目录下执行 <code>go mod init 项目名</code> (项目名可不加),以生成 go.mod 文件。</li> <li>执行 go mod tidy` 更新整理现有的依赖,删除未使用的依赖。</li> </ol><h3>go mod 相关命令</h3>

<code>go mod download</code> 下载 go.mod 文件中指明的所有依赖

<code>go mod tidy</code> 整理现有的依赖,删除未使用的依赖。

<code>go mod graph</code> 查看现有的依赖结构

<code>go mod init</code> 生成 go.mod 文件 (Go 1.13 中唯一一个可以生成 go.mod 文件的子命令)

<code>go mod edit</code> 编辑 go.mod 文件

<code>go mod vendor</code> 导出现有的所有依赖 (事实上 Go modules 正在淡化 Vendor 的概念)

<code>go mod verify</code> 校验一个模块是否被篡改过

<code>go clean -modcache</code> 清理所有已缓存的模块版本数据。

<code>go mod</code> 查看所有 go mod的使用命令。

<h3>参考资料:</h3>

https://segmentfault.com/a/11...

https://learnku.com/articles/...

<h2>links</h2> <ul><li>目录</li></ul> 到此这篇关于“GO 依赖管理工具go Modules(官方推荐)”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
GO 依赖管理工具go Modules(官方推荐)
Golang包管理详解
Go 语言包管理机制深入分析
golang Modules 依赖管理工具使用
go godep包管理工具详解
Go Modules 的使用
Go Modules与GOPROXY 配置
Blog.5 Go Module
Go1.13:使用go mod 管理依赖, 提示cannot find module providing package或cannot find main module
Golang包管理工具govendor的使用

上一篇:golang内存对齐原理 下一篇:golang斗地主
[关闭]
~ ~