go modules详解

go modules详解

[TOC]

go1.11开始,支持使用go modules管理依赖包. 刚加入的适合尝试过, 并不是特别好用, 特别是需要从老的vendor方式切换过来.但是golang包管理一直为人诟病, 官方尝试解决是值得肯定和期待的.

1.13即将正式加入此特性, 有必要对使用方法做一些整理, 避坑备用吧.

原理简介

并没有仔细研究过实现原理,2018年Go team 技术leader Russ Cox在博客发布数篇文章详细阐述了包管理技术方案: vgo(versioned Go), 具体参考vgo wiki, 其主要思想是: 、语义化包导入版本 Semantic Import Versioning, 最小版本选择(MVS)Minimal Version Selection, 可复现、可验证且验证过的构建(方式或过程)Reproducible, Verifiable, Verified Builds, Go模块定义Defining Go Modules等.

vgo和包管理

其中vgo是原型描述, 因其最小版本选择与之前的dep等包管理方法冲突, 随着vgo代码并入主分支,go modules包管理机制成为官方工具, dep等包管理工具可能要退出江湖了.

语义化版本

细节可参考官网

  • 版本格式:主版本号(major).次版本号(minor).修订号(patch)
  • 主版本号:做了不兼容的 API修改
  • 次版本号:向下兼容的功能性新增或改动
  • 修订号:向下兼容的问题修正等

根据这种定义, 主版本号改动即视为不兼容之前大版本, 包管理机制也要使用不同主版本的包得到正确管理, 而次版本号以下的改动视为兼容, 会做合并

module定义

A module is a collection of Go packages stored in a file tree with a go.mod file at its root

模块是Go引用包的集合, 这些包保存在项目根目录的go.mod文件中描述的文件树中.

原理上简单看, 从主模块构建(build list)表开始,递归遍历其下依赖, 升级到指定版本兼容的最新版本, 合并兼容的版本,最后得到final list

对build lists到操作, 具体定义和算法描述(比如upgrade一个module,upgrade所有modules)请参考原文

  • Construct the current build list.
  • Upgrade all modules to their latest versions.
  • Upgrade one module to a specific newer version.
  • Downgrade one module to a specific older version.
  • 实际项目使用会生成2个文件: go.mod, go.sum(checksum)

使用实践

  • 使用Go1.11以上版本, 请关注迭代过程中的改变
  • 是否启用go modules可由环境变量GO111MODULE控制(auto, on, off), 默认为auto: 项目在$GOPAH/src外会自动启动,否则兼容老的vendor方式
  • 虽说项目不再依赖GOPATH环境变量, 但go mod下载的依赖包会cache到$GOPATH/pkg/mod下面, 按版本组织
$GOPATH/pkg/mod/github.com/sirupsen/logrus@v1.4.1

help 文档

目前go mod使用多的是init, tidy等子命令

go help modules
go help mod
go help mod init|tidy|vendor
# go.mod文件帮助
go help go.mod

步骤

基本用法还是比较简单的, 以下为示例:

# 创建project
make hello-mod
touch main.go
# coding... and 导入包,

# go mod 初始化,会生成go.mod, 项目module名为hello-mod
go mod init hello-mod
go mod tidy
cat go.mod
# 或在代码中import,然后直接build或test
go build
# 查看当前包版本信息(包括间接引用),执行对应更新
go list -m -json all
# 带目录路径信息
go list -m -f={{.Dir}}
go get xxxx
go build ./...
# 或者直接run
go run main.go

也可使用vendor方式下载包到项目下.

go init hello-vendor
go mod vendor
go run main.go

最初Russ Cox打算彻底废弃vendor方式, 经社区讨论最终得以保留, 以兼容Go1.11之前版本.

避坑指南

看示例挺简单,实际上还是遇到不少坑的

代理

因为某些原因有些包无法直接下载, 需要代理,目前官方提供:

a module mirror for accelerating Go module downloads, an index for discovering new modules, and a global go.sum database for authenticating module content.

proxy.golang.org - a module mirror
sum.golang.org - an auditable checksum database to authenticate modules.
index.golang.org - an index which serves a feed of new module versions

status应该还是beta, 目前测试在国内可用

# 查看帮助
go help goproxy
# 环境变量设置
export GOPROXY=https://proxy.golang.org
# 类似的代理还有不少,下面这个在香港有服务器, 速度挺快: 
export GOPROXY=https://goproxy.io

go.mod文件

go.mod文件可保证构建过程可重现.

  • module定义模块路径, 比如go init hello-mod指定的hello-mod,子目录下到包可以从此相对路径指定
# 例如之前示例的hello-mod,假设之下有子目录sub包,在代码中包含:
import "hello-mod/sub"
  • require 表示依赖包
replace example.com/some/dependency => example.com/some/dependency v1.2.3
  • exclude 排除某个特定包
  • replace 使用另外版本替代模块版本

这是个文本文件, 可手动修改:

  • 如果依赖包源不可访问, 如若golang.org/x/tools无法访问, 可使用replace
  • 获取特定版本, 或满足某些条件(大于、小于等关系), 在require下对应项修改版本号
  • module query: go mod edit -require='github.com/xxx/xxxx@>=v1.2.3' (老版是go mod -require)
# 修改go.mod
require github.com/sirupsen/logrus <v1.4.2
# 重新运行会重现解析下载满足条件的依赖
go run main.go
# 查看发现版本降级为v1.4.1
cat go.mod
require github.com/sirupsen/logrus v1.4.2

go.sum文件

go.sum为依赖包版本信息加密校验和(the expected cryptographic checksums)

  • 运行go命令会进行校验
  • go mod verify校验本地cache的包与go.sum是否匹配
  • 最好与go.mod一起上传到repo中, 用于下载后进行依赖包校验

build 选项

  • --mod=readonly, 不更新依赖, 如在ci过程中build
  • --mod=vendor, 使用项目顶层目录下的vendor,需要确保vendor包完整准确, 因为依然会忽略其他目录下的vendor包
go run -mod=readonly main.go

升级或降级包

go list -m -json all
go list -m -f={{.Dir}} all
run go get -u # to use the latest minor or patch releases
run go get -u=patch # to use the latest patch releases

社区相关工具

  • github.com/goware/modvendor, 帮助copy额外依赖文件
$ GO111MODULE=on go mod vendor
$ modvendor -copy="**/*.c **/*.h **/*.proto" -v
  • github.com/marwan-at-work/mod, 帮助自动升级/降级模块版本, 修改import路径(如增加版本号)

Command line tool to automatically upgrade/downgrade major versions for modules

GO111MODULE=on go get github.com/marwan-at-work/mod/cmd/mod
# 更新项目自身版本
mod upgrade
cat go.mod
# module hello-vendor/v2
# import "hello-vendor/v2/sub"

# 升级依赖包版本
mod upgrade --mod-name=github.com/x/y

需要注意的是 --mod-name如果是自身, 则go.mod中module不会升版本, 但是代码中引用自身子包的版本增加, 这是否算一个bug呢?

references

  • 见链接
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • 备注:本猿翻译水平有限,请各位看客见谅 翻译内容: go1.11 版本中 go help modules文档内容 ...
    星云数联阅读 2,439评论 0 1
  • vendor 在Go1.5 release的版本的发布vendor目录被添加到除了GOPATH和GOROOT之外的...
    _羊羽_阅读 3,895评论 0 2
  • 受到绍兴同事婚礼的邀请,回了次绍兴。借着机会回学校逛了逛。 男生宿舍7号楼旁的围墙终于被推,加开了一个校门。当初住...
    终俗阅读 547评论 0 0
  • 我期望你成为这样的人,所以我把你写成了故事的主角。悲剧的青春里哪怕有一丝的微光,都是一根救命稻草,拯救了你的一生。...
    意磬阅读 1,153评论 16 15
  • 一、近期的目标:完美的伴侣 二、需要种下的种子:爱与陪伴,智慧,温暖,财富。 三、具体的播种行为 1.今天楼上店铺...
    柔光宝宝阅读 131评论 0 0