仯仯 發表於 2020-2-9 16:21:00

Go依赖管理及Go module使用

<p>Go语言的依赖管理随着版本的更迭正逐渐完善起来。</p>
<h1 id="autoid-0-0-0">依赖管理</h1>
<h2 id="autoid-1-0-0">为什么需要依赖管理</h2>
<p>最早的时候,Go所依赖的所有的第三方库都放在GOPATH这个目录下面。这就导致了同一个库只能保存一个版本的代码。如果不同的项目依赖同一个第三方的库的不同版本,应该怎么解决?</p>
<h2 id="autoid-1-1-0">godep</h2>
<p>Go语言从v1.5开始开始引入<code>vendor</code>模式,如果项目目录下有vendor目录,那么go工具链会优先使用<code>vendor</code>内的包进行编译、测试等。</p>
<p><code>godep</code>是一个通过vender模式实现的Go语言的第三方依赖管理工具,类似的还有由社区维护准官方包管理工具<code>dep</code>。</p>
<h3 id="autoid-1-2-0">安装</h3>
<p>执行以下命令安装<code>godep</code>工具。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:go;gutter:true;">go get github.com/tools/godep
</pre>
</div>
<h3 id="autoid-1-2-1">基本命令</h3>
<p>安装好godep之后,在终端输入<code>godep</code>查看支持的所有命令。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:go;gutter:true;">godep save   将依赖项输出并复制到Godeps.json文件中
godep go       使用保存的依赖项运行go工具
godep get      下载并安装具有指定依赖项的包
godep path   打印依赖的GOPATH路径
godep restore在GOPATH中拉取依赖的版本
godep update   更新选定的包或go版本
godep diff   显示当前和以前保存的依赖项集之间的差异
godep version查看版本信息
</pre>
</div>
<p>使用<code>godep help </code>可以看看具体命令的帮助信息。</p>
<h3 id="autoid-1-2-2">使用godep</h3>
<p>在项目目录下执行<code>godep save</code>命令,会在当前项目中创建<code>Godeps</code>和<code>vender</code>两个文件夹。</p>
<p>其中<code>Godeps</code>文件夹下有一个<code>Godeps.json</code>的文件,里面记录了项目所依赖的包信息。 <code>vender</code>文件夹下是项目依赖的包的源代码文件。</p>
<h3 id="autoid-1-2-3">vender机制</h3>
<p>Go1.5版本之后开始支持,能够控制Go语言程序编译时依赖包搜索路径的优先级。</p>
<p>例如查找项目的某个依赖包,首先会在项目根目录下的<code>vender</code>文件夹中查找,如果没有找到就会去<code>$GOAPTH/src</code>目录下查找。</p>
<h3 id="autoid-1-2-4">godep开发流程</h3>
<ol>
<li>保证程序能够正常编译</li>
<li>执行<code>godep save</code>保存当前项目的所有第三方依赖的版本信息和代码</li>
<li>提交Godeps目录和vender目录到代码库。</li>
<li>如果要更新依赖的版本,可以直接修改<code>Godeps.json</code>文件中的对应项</li>
</ol>
<h2 id="autoid-1-2-5">go module</h2>
<p><code>go module</code>是Go1.11版本之后官方推出的版本管理工具,并且从Go1.13版本开始,<code>go module</code>将是Go语言默认的依赖管理工具。</p>
<h3 id="autoid-1-3-0">GO111MODULE</h3>
<p>要启用<code>go module</code>支持首先要设置环境变量<code>GO111MODULE</code>,通过它可以开启或关闭模块支持,它有三个可选值:<code>off</code>、<code>on</code>、<code>auto</code>,默认值是<code>auto</code>。</p>
<ol>
<li><code>GO111MODULE=off</code>禁用模块支持,编译时会从<code>GOPATH</code>和<code>vendor</code>文件夹中查找包。</li>
<li><code>GO111MODULE=on</code>启用模块支持,编译时会忽略<code>GOPATH</code>和<code>vendor</code>文件夹,只根据 <code>go.mod</code>下载依赖。</li>
<li><code>GO111MODULE=auto</code>,当项目在<code>$GOPATH/src</code>外且项目根目录有<code>go.mod</code>文件时,开启模块支持。</li>
</ol>
<p>简单来说,设置<code>GO111MODULE=on</code>之后就可以使用<code>go module</code>了,以后就没有必要在GOPATH中创建项目了,并且还能够很好的管理项目依赖的第三方包信息。</p>
<p>使用 go module 管理依赖后会在项目根目录下生成两个文件<code>go.mod</code>和<code>go.sum</code>。</p>
<h3 id="autoid-1-3-1">GOPROXY</h3>
<p>Go1.11之后设置GOPROXY命令为:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:go;gutter:true;">export GOPROXY=https://goproxy.cn
</pre>
</div>
<p>Go1.13之后<code>GOPROXY</code>默认值为<code>https://proxy.golang.org</code>,在国内是无法访问的,所以十分建议大家设置GOPROXY,这里我推荐使用goproxy.cn。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:go;gutter:true;">go env -w GOPROXY=https://goproxy.cn,direct
</pre>
</div>
<h3 id="autoid-1-3-2">go mod命令</h3>
<p>常用的<code>go mod</code>命令如下:</p>
<div class="cnblogs_code">
<pre>go mod download    下载依赖的module到本地cache(默认为$GOPATH/pkg/<span style="color: rgba(0, 0, 0, 1)">mod目录)
go mod edit      编辑go.mod文件
go mod graph       打印模块依赖图
go mod init      初始化当前文件夹, 创建go.mod文件
go mod tidy      增加缺少的module,删除无用的module
go mod vendor      将依赖复制到vendor下
go mod verify      校验依赖
go mod why         解释为什么需要依赖</span></pre>
</div>
<h3 id="autoid-1-3-3">go.mod</h3>
<p>go.mod文件记录了项目所有的依赖信息,其结构大致如下:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:go;gutter:true;">module github.com/Q1mi/studygo/blogger

go 1.12

require (
        github.com/DeanThompson/ginpprof v0.0.0-20190408063150-3be636683586
        github.com/gin-gonic/gin v1.4.0
        github.com/go-sql-driver/mysql v1.4.1
        github.com/jmoiron/sqlx v1.2.0
        github.com/satori/go.uuid v1.2.0
        google.golang.org/appengine v1.6.1 // indirect
)
</pre>
</div>
<p>其中,</p>
<ul>
<li><code>module</code>用来定义包名</li>
<li><code>require</code>用来定义依赖包及版本</li>
<li><code>indirect</code>表示间接引用</li>
</ul>
<h4 id="依赖的版本">依赖的版本</h4>
<p>go mod支持语义化版本号,比如<code>go get foo@v1.2.3</code>,也可以跟git的分支或tag,比如<code>go get foo@master</code>,当然也可以跟git提交哈希,比如<code>go get foo@e3702bed2</code>。关于依赖的版本支持以下几种格式:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:go;gutter:true;">gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7
gopkg.in/vmihailenco/msgpack.v2 v2.9.1
gopkg.in/yaml.v2 &lt;=v2.2.1
github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e
latest
</pre>
</div>
<h4 id="replace">replace</h4>
<p>在国内访问golang.org/x的各个包都需要FQ,你可以在go.mod中使用replace替换成github上对应的库。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:go;gutter:true;">replace (
        golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac =&gt; github.com/golang/crypto v0.0.0-20180820150726-614d502a4dac
        golang.org/x/net v0.0.0-20180821023952-922f4815f713 =&gt; github.com/golang/net v0.0.0-20180826012351-8a410e7b638d
        golang.org/x/text v0.3.0 =&gt; github.com/golang/text v0.3.0
)
</pre>
</div>
<h3 id="autoid-1-3-4">go get</h3>
<p>在项目中执行<code>go get</code>命令可以下载依赖包,并且还可以指定下载的版本。</p>
<ol>
<li>运行<code>go get -u</code>将会升级到最新的次要版本或者修订版本(x.y.z, z是修订版本号, y是次要版本号)</li>
<li>运行<code>go get -u=patch</code>将会升级到最新的修订版本</li>
<li>运行<code>go get package@version</code>将会升级到指定的版本号version</li>
</ol>
<p>如果下载所有依赖可以使用<code>go mod download</code>命令。</p>
<h3 id="autoid-1-3-5">整理依赖</h3>
<p>我们在代码中删除依赖代码后,相关的依赖库并不会在<code>go.mod</code>文件中自动移除。这种情况下我们可以使用<code>go mod tidy</code>命令更新<code>go.mod</code>中的依赖关系。</p>
<h3 id="autoid-1-3-6">go mod edit</h3>
<h4 id="格式化">格式化</h4>
<p>因为我们可以手动修改go.mod文件,所以有些时候需要格式化该文件。Go提供了一下命令:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:go;gutter:true;">go mod edit -fmt
</pre>
</div>
<h4 id="添加依赖项">添加依赖项</h4>
<div class="cnblogs_Highlighter">
<pre class="brush:go;gutter:true;">go mod edit -require=golang.org/x/text
</pre>
</div>
<h4 id="移除依赖项">移除依赖项</h4>
<p>如果只是想修改<code>go.mod</code>文件中的内容,那么可以运行<code>go mod edit -droprequire=package path</code>,比如要在<code>go.mod</code>中移除<code>golang.org/x/text</code>包,可以使用如下命令:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:go;gutter:true;">go mod edit -droprequire=golang.org/x/text
</pre>
</div>
<p>关于<code>go mod edit</code>的更多用法可以通过<code>go help mod edit</code>查看。</p>
<h2 id="autoid-1-3-7">在项目中使用go module</h2>
<h3 id="autoid-1-4-0">既有项目</h3>
<p>如果需要对一个已经存在的项目启用<code>go module</code>,可以按照以下步骤操作:</p>
<ol>
<li>在项目目录下执行<code>go mod init</code>,生成一个<code>go.mod</code>文件。</li>
<li>执行<code>go get</code>,查找并记录当前项目的依赖,同时生成一个<code>go.sum</code>记录每个依赖库的版本和哈希值。</li>
</ol>
<h3 id="autoid-1-4-1">新项目</h3>
<p>对于一个新创建的项目,我们可以在项目文件夹下按照以下步骤操作:</p>
<ol>
<li>执行<code>go mod init 项目名</code>命令,在当前项目文件夹下创建一个<code>go.mod</code>文件。</li>
<li>手动编辑<code>go.mod</code>中的require依赖项或执行<code>go get</code>自动发现、维护依赖。</li>
</ol>

</div>
<div id="MySignature" role="contentinfo">
    代码改变世界,脚踏实地,python、Golang。<br><br>
来源:https://www.cnblogs.com/Golanguage/p/12287496.html
頁: [1]
查看完整版本: Go依赖管理及Go module使用