忘掉GOPATH,迎接Go modules,进入Go项目依赖库版本管理新时代

liulaomo · · 1937 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Go SDK 1.13测试版马上就要发布了。从此版本开始,Go modules依赖库版本管理特性将正式开始推荐使用。本文将解释一些和Go modules相关的一些命令和概念。

Module(模块)定义为一些Go代码包的集合。通常体现为一个含有若干代码包的目录。每个模块可以发布一系列版本。版本号使用semver(语义化版本)表示。一个模块可能依赖于其它若干模块;准确说来,是依赖于其它若干模块的各自的某个具体版本。每个模块可以在自己的根目录下的go.mod文件中指定其所依赖的各个模块的具体版本。

如果你所维护的某个模块尚未使用Go modules管理依赖,你可以打开一个命令行终端,进入此模块根目录,运行下面这条命令将此模块转换为一个使用Go modules管理依赖的模块。

go mod init host.prefex/mypkg

其中,host.prefex/mypkg为其它包引入此模块中的包时的引入路径的前缀。常常地,host.prefexgithub.com等源代码托管网站;mypkg常为 user/project 这种形式。当然,你也可以将你自己的域名 my.website 用做引入路径的前缀(host.prefex)。但是这时如果不能从引入路径my.website/mypkg 中判断出此代码包使用何种源代码版本管理工具(比如git/hg/svn等),则my.website网站必须响应 https://my.website/mypkg?go-get=1 HTTPS请求(HTTP也可以但不推荐),并在在HTML的返回体中的<head>部分包含一个<meta>标签来指名具体到哪里下载此模块。(本公众号将另开一篇文章详解自定义域名引入路径。)

当go.mod文件已经创建出来之后,我们可以在此文件中手动指定此模块所要依赖的其它模块和这些以来模块的版本号(版本号必须指定但可以使用伪版本号,比如 <v1.12.3>=v1.5.6latest和分支名master等)。我们也可以运行go build和go test等命令来自动发现并且在go.mod文件中加入依赖模块和它们的具体版本。手动指定的伪模块版本号将被go build等命令更改为确切的版本号。其中

  • latest伪版本号将被解读为最新正式发布版本,正式发布版本是标号为形如vX.Y.Z的语义化版本(semver,X/Y/Z均为整数数字)。
  • 分支名伪版本号将被解读为指定分支的最新提交。
  • <v1.12.3 将被解读为v1.12系列版中最大的小于v1.12.3的版本。

当使用源代码版本管理工具时,一个tag的名称将被视为一个版本号。形如 v1.2.3-pre1 的预发布版本不属于正式版本。(关于模块的版本匹配规则,本公众号将另发一篇文章详述。)

go build等命令将下载并缓存尚未缓存的依赖模块的版本代码,并将各个模块(包括直接和间接依赖)的哈希存储在go.sum文件(和go.mod文件处于同一目录)中。

在一个模块目录下运行 go get a.b.c/x/y@v1.2.3 将在此模块的go.mod文件中加入一个依赖。

默认情况下,go build等命令将访问sumdb(Checksum Database,默认值为 https://sum.golang.org/ )验证各个直接或者间接依赖模块的哈希值是否和各个go.sum中记录的哈希值相匹配。如果不匹配,很可能某些环节出了问题(比如下载的模块代码被人恶意更改了)。(关于sumdb,本公众号将另发一篇文章详述。)

一般说来,go.mod文件中只记录当前模块的直接依赖。每个依赖体现为一条require或者replace指令。比如

module my.website/cmd/myprogram

require github.com/boltdb/bolt v1.3.0
​
replace my.website/mypkg github.com/myname/myproject v1.0.0

其中的 replace 指令表示,当遇到引入路径前缀为 my.website/mypkg 的代码包时,真实的下载的代码包为处于路径 github.com/myname/myprojectv1.0.0版本的模块下的相应代码包。

如果你的一个旧项目是使用其它流行第三方工具(比如deps和glide等)来管理包依赖的,则在此项目下运行 go mod init host.prefex/mypkg 命令将自动将此项目转换为一个使用 go modules 管理依赖的项目。

如果你的一个新项目需要依赖于一个当前正使用其它流行第三方工具来管理包依赖的库,则请到此库的根目录下运行以下 go mod init a.b/c 命令(引入路径可任意),然后将生成的go.mod中的所有require指令复制到你的新项目下的go.mod文件中。(至少对于目前的Go SDK 1.12是如此,以后的Go SDK版本可能会对此过程进行改进。)

一些其它的和modules相关的常用命令和命令选项:

  • go list -m all 列出所有的(包括直接的和间接的)将在go build中使用的各个模块和它们的具体版本号
  • go list -u -m all 列出所有的(包括直接和间接)使用的各个模块目前可用的小更新或者补丁版本号
  • go get -u or go get -u=patch 将目前所有的(直接和间接)依赖的模块的版本号更新到最新可用的小更新或者补丁版本号。
  • go mod tidygo.mod中删除目前已经不再使用的依赖模块和加入其它操作系统和架构所需的依赖
  • go mod vendor 将所有依赖放入当前模块下的vendor子目录中
  • go build -mod vendor 使用当前模块下的vendor子目录中的依赖代码(而不是缓存中依赖模块代码)来编译构建

本文首发在微信Go 101公众号,欢迎各位转载本文。Go 101公众号将尽量在每个工作日发表一篇原创短文,有意关注者请扫描下面的二维码。

image

关于更多Go语言编程中的事实、细节和技巧,请访问《Go语言101》项目 https://github.com/golang101/golang101


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:liulaomo

查看原文:忘掉GOPATH,迎接Go modules,进入Go项目依赖库版本管理新时代

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1937 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传