您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Go语言

一文详细了解 Go Module

时间:2019-08-29 11:39:33  来源:  作者:
一文详细了解 Go Module

 

1 速览

在正式了解Golang Modules之前,我们先速览一下其使用方式。

在$GOPATH之外的任意地方,创建一个文件夹:

$ mkdir -p /tmp/hello
$ cd /tmp/hello

然后初始化一个新的Module:

$ go mod init github.com/olzhy/hello

输出:

go: creating new go.mod: module github.com/olzhy/hello

go.mod内容为:

module github.com/olzhy/hello
go 1.12

然后写一段代码:

$ cat < hello.go
package main
import (
 "fmt"
 "github.com/olzhy/quote"
)
func main() {
 fmt.Println(quote.Hello())
}
EOF

build一下:

$ go build
go: finding github.com/olzhy/quote latest
go: downloading github.com/olzhy/quote v0.0.0-20190510033103-5cb7d4598cfa
go: extracting github.com/olzhy/quote v0.0.0-20190510033103-5cb7d4598cfa

go.mod内容为:

module github.com/olzhy/hello
go 1.12
require github.com/olzhy/quote v0.0.0-20190510033103-5cb7d4598cfa

可以看到,其会从https://github.com/olzhy/quote master分支拉取最新提交5cb7d4598cfa。

该依赖工程非Module管理模式,其仅有两个文件:

hello.go
README.md

现在给依赖工程打一个TAG,名为v1.0.0。

然后hello工程更新依赖:

$ go get -u
go: finding github.com/olzhy/quote v1.0.0
go: downloading github.com/olzhy/quote v1.0.0
go: extracting github.com/olzhy/quote v1.0.0

查看go.mod内容为:

module github.com/olzhy/hello
go 1.12
require github.com/olzhy/quote v1.0.0

如下为使用Golang Module后的日常工作流。

每日工作流:

  • a)源码根据需要加入包引入语句;
  • b)标准命令,如go build及go test等会自动更新go.mod并下载依赖包;
  • c)当需要特定版本时,可以使用诸如go get foo@v1.2.3,go get foo@master,go get foo@e3702bed2命令或直接编辑go.mod文件。

其它通用命令:

  • a)go list -m all 查看一次构建使用的直接及间接依赖的最终版本;
  • b)go list -u -m all 查看直接及间接依赖的可用的小版本或补丁版本更新;
  • c)go get -u 或 go get -u=patch 将直接与间接依赖更新为最新小版本或补丁版本;
  • d)go build ./... 或 go test ./... 构建或测试模块中的所有包;
  • e)go mod tidy 从go.mod清理不再使用的包;
  • f)go mod edit -replace foo@v1.2=../foo 替换依赖为本地复制或指定版本;
  • g)go mod vendor 转换为vendor依赖方式。

2 概念

2.1 模块

Module是一组相关Go package的集合,其作为一个单独的单元来版本化。

Module记录精确的依赖项,提供可重复的构建。

通常,一个版本控制仓库仅包含一个Module(支持单仓库多Module,但其会比单仓库单Module复杂很多)。

仓库、模块与包的关系:

  • a)一个仓库包含一个或多个模块;
  • b)一个模块包含一个或多个包;
  • c)一个包在一个文件夹包含一个或多个.go文件。

模块必须以语义学版本命名,格式为v(主版本).(小版本).(补丁),诸如v0.1.0、v1.2.3,v1.5.0-rc.1等。

模块由一组源文件树在根目录定义一个go.mod文件,模块源码可以位于GOPATH之外,有如下原语module,require,replace,exclude。

如下为github.com/olzhy/hello模块的go.mod文件示例内容:

module github.com/olzhy/hello
require (
 github.com/some/dependency v1.2.3
 github.com/another/dependency/v4 v4.0.0
)

可以看到,一个模块通过module原语声明模块ID,其标识模块路径。该模块下某一个包的被引用路径由该模块路径与自go.mod所在路径起一直到包的路径止的相对路径共同决定。

如,一个模块在go.mod声明其ID为example.com/my/module,那么引用该模块下mypkg包的代码为:

import "example.com/my/module/mypkg"

2.2 版本选择

若源码中增加了go.mod中未require的新的依赖包,绝大多数诸如go build,go test命令会自动找到对应的包并在go.mod中采用require原语加入该直接依赖的最高版本

例如,您依赖的模块M的带标签的发布版本为v1.2.3,那么您的go.mod会新加入require M v1.2.3这一行语句,意味着依赖模块M所允许的版本>= v1.2.3并< v2(v2被认为与v1不兼容)。 最小版本选择算法用于对一次构建的所有模块选择版本,对于每个模块,采用该算法选择的版本为语义学最高版本

下面举个例子:

若您依赖的模块A依赖D(require D v1.0.0),而您依赖的模块B同样依赖D(require D v1.1.1),然后,最小版本选择(选择最高的版本)将会选择v1.1.1版本的D。而选择v1.1.1版本的D是一致的,即使将来发布了v1.2.0版本的D。

这样即可保持100%可重复构建。当然您也可以手动升级D为最新可用版本或者指定其为其它版本。

查看所选模块版本列表(包括间接依赖),可以使用:

go list -m all

2.3 语义学版本引用

Go多年来推荐的包版本化方式:

开放使用的包在演进时应保持向后兼容的准则,Go 1兼容性准则即是一个好的参考。不要移除已导出的名称,若要加一个新功能,需加一个新接口,不要改动老接口名。实在需要推倒之前的,请创建一个新包,以新的路径而被引用。

最后一句很重要,若破坏了兼容性,需更改包的引用路径。

对Go 1.11模块而言,引用兼容性准则可以概述为:

若新包沿用旧包的引用路径,新包必须向后兼容旧包。

参考语义学版本命名规则,当一个原始为v1或v1以上的包发生了不兼容变更,该包需要更改主版本。

所以,根据引用兼容性准则及语义学版本命名规则(合称为语义学版本引用),主版本需要包含在引用路径内。这样即可保障不兼容的主版本升级时,引用路径即会改变。

根据语义学版本引用规则,选用Go Module的代码必须遵守如下规则:

  • a)语义学版本命名;
  • b)若一个Module的版本为v2及以上,模块的主版本必须包含在模块路径及引用路径中(例如,声明方:module github.com/my/mod/v2,引用方:require github.com/my/mod/v2 v2.0.0,包引用处:import "github.com/my/mod/v2/mypkg");
  • c)例外,若模块主版本为v0或v1,模块路径及引用路径无须包含主版本。

通常来讲,引用路径不同的包是两个全然不同的包(如math/rand和crypto/rand是两个不同的包)。同样,包含不同主版本的引用路径所标识的包亦是两个不同的包。因此,example.com/my/mod/mypkg与example.com/my/mod/v2/mypkg是不同的包,且可能会在一次构建中同时引用。

因有些模块还未转换为Module方式,过度期,会支持如下几个例外:

  • a)gopkg.in
  • 会继续支持gopkg.in/yaml.v1或gopkg.in/yaml.v2等引用方式。
  • b)当引用还未Module化的v2+版本包时,会有'+incompatible'后缀。
  • c)当Module模式未开启时,采用最小模块兼容性。

即在Go 1.11邻近版本,不开启Module模式时(GO111MODULE=off),引用v2或以上版本,不会将版本加入路径中。

3 使用

3.1 模块支持激活

安装Go 1.11及以上版本,然后可以使用如下两种方式中的任一种激活模块支持。

  • a)在$GOPATH/src文件夹之外使用go命令,且当前文件夹或其上层文件夹包含go.mod文件,而GO111MODULE环境变量未设置或设置为了auto;
  • b)设置GO111MODULE=on,然后调用go命令。

即在$GOPATH/src之外使用模块支持,无需设置GO111MODULE环境变量,而在$GOPATH/src使用模块支持,需将GO111MODULE设置为on。

3.2 定义一个模块

a)进入对应文件夹

$ cd path

该文件夹可以为设置GO111MODULE=on的$GOPATH/src,或该文件夹之外的任意路径。

b)执行go mod init

$ go mod init github.com/my/repo

若在初始化一个v2+的模块,需要手动更改go.mod文件及.go代码,以在引用路径及模块路径加入版本信息(语义学版本引用)。

c)构建模块

$ go build ./...

“./...”模式匹配了当前模块下的所有包,go build将自动增加缺失的包。

d)测试模块

$ go test ./...

或者执行如下语句,可以运行模块内的测试及所有直接及间接依赖测试以检查不兼容问题。

$ go test all

3.3 依赖升降级

可以使用go get命令进行日常依赖升级及降级,其会自动更新go.mod文件,当然您也可以手动编辑go.mod文件。

当然,go get也如go build,go test一样,会自动加入缺失的依赖包。

查看可用的小版本或补丁更新,可以执行:

$ go list -u -m all

将直接或间接依赖更新为最新的小版本或补丁版本,可以执行:

$ go get -u

仅更新为补丁版本,可以执行:

$ go get -u=patch

go get foo等同于go get foo@latest,会将foo更新为最新版本。

当有语义学版本时,最新版本为语义学最新版本,没有时,为最新的提交。

一个通常错误的认为是,go get -u foo仅获取最新版本的foo。其实其还会获取foo的直接或间接依赖的最新版本。

更新版本,推荐的做法是先运行go get foo,好使时再运行go get -u foo。

进行版本升降级时,可以使用@version后缀,如:

$ go get foo@v1.6.2

$ go get foo@e3702bed2

还支持模块查询,如:

$ go get foo@'<v1.6.2'

使用分支名称,可以不考虑其是否有语义学版本,而更新为最新的分支提交。

$ go get foo@master

版本升降级后,需测试是否有不兼容问题:

$ go test all

3.4 模块版本发布

发布前执行如下命令,以删减未使用的包。

go mod tidy

然后执行如下命令,保证兼容性。

go test all

然后发布时,需将go.sum文件与go.mod一起提交。

发布v2及以上版本时需注意满足语义学版本引用规则,版本需包含在模块路径及引用路径中。创建一个v2及以上的版本,有如下两种方式:

a)不创建子文件夹

go.mod文件包含vN路径(如:module github.com/my/module/v3),模块内的包引用亦需修改为包含版本的格式(如:import "github.com/my/module/v3/mypkg")。

b)创建子文件夹

创建vN子文件夹,且将go.mod放至该文件夹下,模块路径需以/vN结尾,然后将代码拷贝至vN子文件夹下,然后更新模块内的包引用路径(如:import "github.com/my/module/v3/mypkg")。

最后,创建一个满足语义学版本的tag,推送至仓库即可。

但需注意子模块的情形,该种情形tag需包含前缀。

如,我们有模块example.com/repo/sub/v2,然后想发布版本v2.1.6,仓库为example.com/repo,子模块定义在sub/v2/go.mod,提交时tag需命名为sub/v2.1.6。

参考资料

[1] https://github.com/golang/go/wiki/Modules

[2] https://research.swtch.com/vgo

原文链接:https://leileiluoluo.com/posts/golang-modules.html

本文作者:磊磊落落的博客



Tags:Go Module   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
自从在Go 1.11和更高版本中引入了Go的新的依赖管理系统以来,GoLang开发人员已经接受了包版本控制解决方案。这样做的用户可以使用GoCenter存储库中的 不可变 公共Go 模块,并通...【详细内容】
2020-03-05  Tags: Go Module  点击:(32)  评论:(0)  加入收藏
1 速览在正式了解Golang Modules之前,我们先速览一下其使用方式。在$GOPATH之外的任意地方,创建一个文件夹:$ mkdir -p /tmp/hello$ cd /tmp/hello然后初始化一个新的Module:$...【详细内容】
2019-08-29  Tags: Go Module  点击:(217)  评论:(0)  加入收藏
▌简易百科推荐
zip 是一种常见的归档格式,本文讲解 Go 如何操作 zip。首先看看 zip 文件是如何工作的。以一个小文件为例:(类 Unix 系统下)$ cat hello.textHello!执行 zip 命令进行归档:$ zip...【详细内容】
2021-12-17  Go语言中文网    Tags:Go语言   点击:(13)  评论:(0)  加入收藏
大家好,我是 polarisxu。前段时间,Russ Cox 明确了泛型相关的事情,原计划在标准库中加入泛型相关的包,改放到 golang.org/x/exp 下。目前,Go 泛型的主要设计者 ianlancetaylor 完...【详细内容】
2021-11-30  Go语言中文网    Tags:slices 包   点击:(24)  评论:(0)  加入收藏
前言最近因为项目需要写了一段时间的 Go ,相对于 Java 来说语法简单同时又有着一些 Python 之类的语法糖,让人大呼”真香“。 但现阶段相对来说还是 Python 写的多一些,偶尔还...【详细内容】
2021-11-25  crossoverJie    Tags:Go   点击:(29)  评论:(0)  加入收藏
go-micro是基于 Go 语言用于开发的微服务的 RPC 框架,主要功能如下:服务发现,负载均衡 ,消息编码,请求/响应,Async Messaging,可插拔接口,最后这个功能牛p安装步骤安装proto...【详细内容】
2021-09-06    石老师小跟班  Tags:go-micro   点击:(197)  评论:(0)  加入收藏
GoLand 2021.2 EAP 5 现已发布。用户可以从工具箱应用程序中获得 EAP 构建,也可以从官方网站手动下载。并且从此 EAP 开始,只有拥有有效的 JetBrains 帐户才能加入该计划。手...【详细内容】
2021-06-29  IT实战联盟  今日头条  Tags:GoLand   点击:(185)  评论:(0)  加入收藏
作者:HDT3213今天给大家带来的开源项目是 Godis:一个用 Go 语言实现的 Redis 服务器。支持: 5 种数据结构(string、list、hash、set、sortedset) 自动过期(TTL) 发布订阅、地理位...【详细内容】
2021-06-18  HelloGitHub  今日头条  Tags:Go   点击:(125)  评论:(0)  加入收藏
统一规范篇合理规划目录本篇主要描述了公司内部同事都必须遵守的一些开发规矩,如统一开发空间,既使用统一的开发工具来保证代码最后的格式的统一,开发中对文件和代码长度的控制...【详细内容】
2021-05-18  1024课堂    Tags:Go语言   点击:(232)  评论:(0)  加入收藏
闭包概述 闭包不是Go语言独有的概念,在很多编程语言中都有闭包 闭包就是解决局部变量不能被外部访问的一种解决方案 是把函数当作返回值的一种应用 代码演示总体思想:在函数...【详细内容】
2021-05-14  HelloGo  今日头条  Tags:Go语言   点击:(223)  评论:(0)  加入收藏
一时想不开,想了解一下Go语言,于是安装了并体验了一下。下载1. 进入golang.google.cn 点击Download Go 2.选择对应的操作系统,点击后开始下载。 安装1. windows下执行傻瓜式安...【详细内容】
2021-05-12  程序员fearlazy  fearlazy  Tags:Go语言   点击:(236)  评论:(0)  加入收藏
1.简介channel是Go语言的一大特性,基于channel有很多值得探讨的问题,如 channel为什么是并发安全的? 同步通道和异步通道有啥区别? 通道为何会阻塞协程? 使用通道导致阻塞的协程...【详细内容】
2021-05-10  程序员麻辣烫  今日头条  Tags:Go通道   点击:(274)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条