Go语言 Modules基础

1. 简介

GO Modules 也称作 go mod 是golang 官方最新的几个golang 版本中推出的 管理方式或者称作模块支持

golang 中 modules (模块)是什么意思呢?

一个模块是一系列 Go 代码包 的集合,它们保存在同一个文件树中。文件树的根目录中包含了一个 go.mod 文件。go.mod 文件定义了一个模块的 module path,这就是模块根目录的导入路径。go.mod 文件还定义了模块的 dependency requirements(依赖项要求),即为了编译本模块,需要用到哪些其它的模块。每一项依赖项要求都包含了依赖项的 module path,还要指定它的语义版本号

在最新的golang版本golang 1.13中是默认的包管理方式,那么在golang的后期版本中 Go Modules 基本可以认为是官方推荐的依赖管理工具

GO modules 是解决啥问题的?

Golang在早期的版本中(golang 1.11版本之前) 包管理一直没有一个统一方案,表现出问题如:

  1. 所有的依赖包都必须在GOPATH同一个库只能保存一个版本的代码,那么不同的项目要依赖同一个包的不同版本那就很尴尬了.
  2. 工作目录必须在 GOPATH/src 目录下

使用了Go Modules 之后就可在GOPATh/src 之外创建目录和管理包了

我们大概回顾一下

  1. golang 1.5 版本之前所有的依赖包都必须放在 GOPATH 下面,没有版本管理
  2. golang 1.5 版本之后推出 vendor 机制
  3. golang 1.9 版本出现了包管理工具 dep
  4. golang1.11 版本推出 modules 机制对包进行管理,在之后的版本中modules 逐步得到了加强, 在golang1.13 中成为默认的包管理方式并且是默认开启的

2. 基础命令

go mod 的命令其实不多

我们打开命令行工具

$ go help mod
Go mod provides access to operations on modules.

Note that support for modules is built into all the go commands,
not just 'go mod'. For example, day-to-day adding, removing, upgrading,
and downgrading of dependencies should be done using 'go get'.
See 'go help modules' for an overview of module functionality.

Usage:

        go mod <command> [arguments]

The commands are:

        download    download modules to local cache
        edit        edit go.mod from tools or scripts
        graph       print module requirement graph
        init        initialize new module in current directory
        tidy        add missing and remove unused modules
        vendor      make vendored copy of dependencies
        verify      verify dependencies have expected content
        why         explain why packages or modules are needed

Use "go help mod <command>" for more information about a command.

显示的 go mod 实际命令只有如下几个

命令 意思
go mod download 下载依赖的Module到本地缓存
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 解释package或者modules为啥被依赖

3. 基本使用

3.1 go mod init

我们在非GOPATH/src 目录下执行

go mod init 后面是模块名称 ,名称自定义即可

$ go mod init github.com/captain/modDemo
go: creating new go.mod: module github.com/captain/modDemo

这样在项目(模块)目录下多出了一个文件go.mod 文件

我们看看go.mod 中的内容

module github.com/captain/modDemo

go 1.12

我们下载一个依赖包试试

// 执行 如下命令
go get -u github.com/gin-gonic/gin

初次执行下依赖包的命令后会多出一个文件 go.sum

go.sum 是由 go命令行工具维护的,其中记录了每个依赖库的版本和哈希值,其作用是确保项目依赖的模块不会发生变化

执行完之后,我们再看看go.mod 的内容

module github.com/apiDemo

go 1.12

require (
  github.com/gin-gonic/gin v1.5.0 // indirect
  github.com/go-playground/universal-translator v0.17.0 // indirect
  github.com/json-iterator/go v1.1.8 // indirect
  github.com/leodido/go-urn v1.2.0 // indirect
  github.com/mattn/go-isatty v0.0.10 // indirect
  github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
  github.com/modern-go/reflect2 v1.0.1 // indirect
  github.com/stretchr/objx v0.2.0 // indirect
  golang.org/x/crypto v0.0.0-20191128160524-b544559bb6d1 // indirect
  golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933 // indirect
  golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
  golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 // indirect
  golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d // indirect
  golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 // indirect
  gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
  gopkg.in/go-playground/validator.v9 v9.30.2 // indirect
  gopkg.in/yaml.v2 v2.2.7 // indirect
)

go.mod 文件简介:

module 用来定义包名和我们初始化的包名是一致的

require 定义依赖的包及其对应的版本

indirect 标识间接引用

3.1 下载指定版本的依赖库

go list -m all 列出当前模块和它的依赖库

$ go list -m all
github.com/captain/modDemo
github.com/davecgh/go-spew v1.1.1
github.com/gin-contrib/sse v0.1.0
github.com/gin-gonic/gin v1.5.0
github.com/go-playground/locales v0.13.0
github.com/go-playground/universal-translator v0.17.0
github.com/golang/protobuf v1.3.2
github.com/google/gofuzz v1.0.0
github.com/json-iterator/go v1.1.8
github.com/leodido/go-urn v1.2.0
github.com/mattn/go-isatty v0.0.10
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.2.0
github.com/stretchr/testify v1.4.0
github.com/ugorji/go v1.1.7
github.com/ugorji/go/codec v1.1.7
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413
golang.org/x/net v0.0.0-20191207000613-e7e4b65ae663
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab
golang.org/x/text v0.3.2
golang.org/x/tools v0.0.0-20191206204035-259af5ff87bd
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15
gopkg.in/go-playground/assert.v1 v1.2.1
gopkg.in/go-playground/validator.v9 v9.30.2
gopkg.in/yaml.v2 v2.2.7

go list -m -versions 库名地址 列出一个模块能用的版本

$ go list -m -versions github.com/gin-gonic/gin
github.com/gin-gonic/gin v1.1.1 v1.1.2 v1.1.3 v1.1.4 v1.3.0 v1.4.0 v1.5.0

go mod tidy 删除无效的modules

$ go mod tidy
$ go list -m all
github.com/captain/modDemo

我们拿比较常见的 一个库xrom做示例 下载指定的版本

可见 xorm可用的版本很多

$ go list -m -versions github.com/go-xorm/xorm
github.com/go-xorm/xorm v0.2.1 v0.2.2 v0.2.3 v0.3.1 v0.3.2 v0.4.1 v0.4.2 v0.4.3 v0.4.4 v0.4.5 v0.5.0 v0.5.1 v0.5.2 v0.5.3 v0.5.4 v0.5.6 v0.5.7 v0.5.8 v0.6.2 v0.6.3 v0.6.4 v0.6.5 v0.6.6 v0.7.0 v0.7.1 v0.7.2 v0.7.3 v0.7.4 v0.7.5 v0.7.6 v0.7.7 v0.7.8 v0.7.9

go mod 想下载指定的版本 通常我们有三种做法

  1. go get 包路径@v版本号
  2. go get 包路径@分支 分支是指在github上提交的分支
  3. go get 包路径@git提交的哈希

我们看到目前 xorm 最新版本是 v0.7.9 但是我想下载比较旧一点的版本 v0.7.5

$ go get github.com/go-xorm/xorm@v0.7.5
go: finding github.com/go-xorm/xorm v0.7.5
go: finding github.com/jackc/pgx v3.3.0+incompatible
go: finding xorm.io/core v0.7.0
go: finding github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4
go: finding github.com/cockroachdb/apd v1.1.0
go: finding xorm.io/builder v0.3.5
go: finding github.com/jackc/fake v0.0.0-20150926172116-812a484cc733
go: finding github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24
go: finding github.com/ziutek/mymysql v1.5.4
go: finding github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a
go: finding golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468
go: finding google.golang.org/appengine v1.6.0
go: finding golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed
go: downloading github.com/go-xorm/xorm v0.7.5
go: extracting github.com/go-xorm/xorm v0.7.5
go: downloading xorm.io/builder v0.3.5
go: downloading xorm.io/core v0.7.0
go: extracting xorm.io/builder v0.3.5
go: extracting xorm.io/core v0.7.0

$ cat go.mod
module github.com/captain/modDemo

go 1.12

require github.com/go-xorm/xorm v0.7.5 // indirect

3.2 更新依赖库

通常下载一个包没有明确指定版本,那么下载的包就是当前的最新版本

我们还是拿 xorm 包作为示例

$ go get github.com/go-xorm/xorm
go: finding github.com/jackc/pgx v3.6.0+incompatible
go: finding xorm.io/builder v0.3.6
go: finding xorm.io/core v0.7.2-0.20190928055935-90aeac8d08eb
go: downloading github.com/go-xorm/xorm v0.7.9
go: extracting github.com/go-xorm/xorm v0.7.9
go: downloading xorm.io/core v0.7.2-0.20190928055935-90aeac8d08eb
go: downloading xorm.io/builder v0.3.6
go: extracting xorm.io/core v0.7.2-0.20190928055935-90aeac8d08eb
go: extracting xorm.io/builder v0.3.6
$ cat go.mod
module github.com/captain/modDemo

go 1.12

require (
        github.com/go-xorm/xorm v0.7.9 // indirect
        github.com/golang/protobuf v1.3.1 // indirect
        github.com/kr/pretty v0.1.0 // indirect
        github.com/satori/go.uuid v1.2.0 // indirect
        golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 // indirect
        golang.org/x/net v0.0.0-20190603091049-60506f45cf65 // indirect
        golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed // indirect
        golang.org/x/text v0.3.2 // indirect
        golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468 // indirect
)

我们看到了结果现在xorm 更新到了当前最新版本v0.7.9

那我可不可以更新到一个指定的版本呢?其实做法是一样的就是指定一个版本号就可以了

$ go get github.com/go-xorm/xorm@v0.7.7
go: finding github.com/go-xorm/xorm v0.7.7
go: finding xorm.io/builder v0.3.6-0.20190906062455-b937eb46ecfb
go: downloading github.com/go-xorm/xorm v0.7.7
go: extracting github.com/go-xorm/xorm v0.7.7

$ cat go.mod
module github.com/captain/modDemo

go 1.12

require (
        github.com/go-xorm/xorm v0.7.7 // indirect
        github.com/golang/protobuf v1.3.1 // indirect
        github.com/kr/pretty v0.1.0 // indirect
        github.com/satori/go.uuid v1.2.0 // indirect
        golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 // indirect
        golang.org/x/net v0.0.0-20190603091049-60506f45cf65 // indirect
        golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed // indirect
        golang.org/x/text v0.3.2 // indirect
        golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468 // indirect
        xorm.io/builder v0.3.6 // indirect
        xorm.io/core v0.7.2-0.20190928055935-90aeac8d08eb // indirect
)

3.3 go get简介

go get 命令可以远程拉取更新代码包和依赖包,并自动完成编译和安装

go get 命令实际是分成了两步操作 1. 下载源码包 2.执行 go insert

简单的理解是 :

go get = git clone + go insert

这是一个常见的远程包的格式 : github.com/go-xorm/xorm

github.com 是网站域名

go-xorm 我们可以理解为作者或者机构名称

xorm 就是项目名称

go get 命令的具体详情可以查看它的帮助命令

对命令附带的可用参数有很详细的介绍

$ go help get
usage: go get [-d] [-m] [-u] [-v] [-insecure] [build flags] [packages]

Get resolves and adds dependencies to the current development module
and then builds and installs them.

The first step is to resolve which dependencies to add.

我们只看几个很常见的

-d 只下载,而不安装

-u 强制使用网络去更新包和它的依赖包

-v 显示执行的命令

-t 同时也下载需要为运行测试所需要的包

-fix 让命令程序在下载代码包后先执行修正动作,而后再进行编译和安装。

-x 打印安装的具体过程

-insecure 允许命令程序使用非安全的scheme(如HTTP)去下载指定的代码包

-f 仅在使用-u标记时才有效。该标记会让命令程序忽略掉对已下载代码包的导入路径的检查

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

推荐阅读更多精彩内容