Go语言--Go Moudule系列文章学习

最新发表的GO1.14支持在生产环境中使用Module Support,此系列通过阅读官方的系列文档给出我自己的个人总结。

Part1 Using Go Modules

简单定义

,Module是存储在文件树中的Go软件包的集合,其根目录中有go.mod文件。
go.mod文件定义模块的模块路径(这也是用于根目录的导入路径)及其依赖关系要求,这些依赖关系是为了能成功build所必须的其他模块。 每个依赖性要求都写为模块路径和特定的语义版本。

常见操作

Creating a new module

go mod init modulename

使用的modulename就是你生成模块的名称

Adding a dependency

package hello

import "rsc.io/quote"

func Hello() string {
    return quote.Hello()
}

Go module的主要动机是改善使用其他开发人员编写的代码(即添加对代码的依赖)的体验。
当第一遍运行go test会帮你下载所需要的软件包

$ go test
go: finding rsc.io/quote v1.5.2
go: downloading rsc.io/quote v1.5.2
go: extracting rsc.io/quote v1.5.2
go: finding rsc.io/sampler v1.3.0
go: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: downloading rsc.io/sampler v1.3.0
go: extracting rsc.io/sampler v1.3.0
go: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: extracting golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
PASS
ok      example.com/hello    0.023s

运行go test,会自动下载需要的rsc.io/quote包,go会将寻找到该包最新的稳定版本,并加载其依赖的其他包,但是在go.mod中只会记录直接依赖项

module example.com/hello
go 1.12
require rsc.io/quote v1.5.2

当第二次运行的时候,他不会重复下载软件包,因为现在的go.mod是最新的且下载的模块也缓存在了$GOPATH/pkg/mod中

添加一个直接依赖项通常也会带来其他间接依赖项,命令go list -m all列出当前模块及其所有依赖项

$ go list -m all
example.com/hello
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0

除了go.mod之外,go命令还会维护一个名为go.sum的文件,其中包含特定模块版本内容的预期加密哈希:
go命令使用go.sum文件来确保这些模块的将来下载与第一次下载时检索的位相同,以确保您的项目所依赖的模块不会由于恶意,意外或其他原因而意外更改。 应该将go.mod和go.sum都放到版本控制的检查中。

Upgrading dependencies
对于Go模块,使用语义版本标记引用版本。 语义版本包括三个部分:主要,次要和补丁。 例如,对于v0.1.2,主要版本为0,次要版本为1,补丁版本为2。

 go list -m -versions rsc.io/sampler //获取可用版本
 go get rsc.io/sampler@v1.3.1 //指定特殊版本

Adding a dependency on a new major version
go命令允许构建最多包含任何特定模块路径的一个版本,即每个主要版本的至多:一个rsc.io/quote,一个rsc.io/quote/v2,一个rsc.io/quote/ v3,依此类推。 这为模块作者提供了关于可能重复单个模块路径的明确规则:程序无法同时使用rsc.io/quote v1.5.2和rsc.io/quote v1.6.0来构建。 同时,允许模块的不同主要版本(因为它们具有不同的路径)使模块使用者可以逐步升级到新的主要版本。 在此示例中,我们想使用rsc / quote / v3 v3.1.0中的quote.Concurrency,但尚未准备好迁移rsc.io/quote v1.5.2的使用,则可以使用go mod的此特性引入v3版本的包。 在大型程序或代码库中,增量迁移的能力尤为重要。

package hello

import (
    "rsc.io/quote"
    quoteV3 "rsc.io/quote/v3"
)

func Hello() string {
    return quote.Hello()
}

func Proverb() string {
    return quoteV3.Concurrency()
}

Upgrading a dependency to a new major version
可以使用

 go doc rsc.io/quote/v3
 package quote // import "rsc.io/quote"

Package quote collects pithy sayings.

func Concurrency() string
func GlassV3() string
func GoV3() string
func HelloV3() string
func OptV3() string

查看包内所含的方法,若是新版本包已经包含了旧版本方法则可以使用新版本去代替旧版本

Removing unused dependencies

go mod tidy

使用如上命令可以清除那些未被使用的依赖
命令总结:
Go模块是Go中依赖管理的未来。 现在,所有受支持的Go版本(即Go 1.11和Go 1.12)都提供模块功能。

这篇文章使用Go模块介绍了这些工作流程:

go mod init创建一个新模块,初始化描述它的go.mod文件。
go build,go test和其他软件包构建命令会根据需要向go.mod添加新的依赖项。
go list -m all打印当前模块的依赖关系。
go get 获取更改所需的依赖版本(或添加新的依赖)。
go mod tidy删除未使用的依赖项。

Part2 Migrating to Go Modules

总结:
1.go mod init modulename(建议使用custom import path)
2.go mod tidy(获取文件依赖)
3.go build(检测编译是否成功)
注意:
若项目使用了类似的依赖软件,则要特别注意新引入的包与旧包的版本比较,有不同的可以进行单独修改

Part3 Publishing Go Modules

每个在go.mod中的依赖module都有semantic version,该version有三种格式:
当您对模块的公共API进行向后不兼容的更改时,请增加MAJOR版本。 仅应在绝对必要时执行此操作。
当您对API进行向后兼容的更改时(例如更改依赖关系或添加新的函数,方法,结构字段或类型),请增加MINOR版本。
在进行不影响模块公共API或依赖项的细微更改(例如修复错误)之后,增加PATCH版本。
go.mod中引用的版本可以是在存储库中标记的显式版本(例如v1.5.2),也可以是基于特定提交(commit)的伪版本(例如v0.0.0-20170915032832-14c0d48ead0c )。
建议使用显式版本,这样标明特定版本已经经过全面测试并可以使用。
如何标识新版本
v0: the initial, unstable version
1.go mod tidy,删除模块不必要的依赖
2.运行 go test,确定所有都可以工作
3. 使用git tag 打tag
4. push新的tag到远端代码仓库

$ go mod tidy
$ go test ./...
ok      example.com/hello       0.015s
$ git add go.mod go.sum hello.go hello_test.go
$ git commit -m "hello: changes for v0.1.0"
$ git tag v0.1.0
$ git push origin v0.1.0

v1: the first stable version
当你确定你的模块api已经平稳了,你可以发布v1.0.0作为v1的主要版本。

$ go mod tidy
$ go test ./...
ok      example.com/hello       0.015s
$ git add go.mod go.sum hello.go hello_test.go
$ git commit -m "hello: changes for v1.0.0"
$ git tag v1.0.0
$ git push origin v1.0.0
$

Part4 Go Modules: v2 and Beyond

核心意思是更新项目的时候若是有向后不兼容的内容,但是为了不干扰已经使用了旧版本的用户,可以在master分支中开发多个主要版本。
以github.com/googleapis/gax-go,为例子
1.在目录下创建v2并拷贝所有文件进入

$ mkdir v2
$ cp *.go v2/
building file list ... done
call_option.go
gax.go
header.go
invoke.go
tools.go

sent 10588 bytes  received 130 bytes  21436.00 bytes/sec
total size is 10208  speedup is 0.95
$

2.创建v2的go.mod文件,通过拷贝当前的mod文件进入期内,修改其module

$ cp go.mod v2/go.mod
$ go mod edit -module github.com/googleapis/gax-go/v2 v2/go.mod

3.在需要更改go module的地方要更改文件包名称,例如,要修改所有的github.com/my/project到github.com/my/project/v2:

$ find . -type f \
    -name '*.go' \
    -exec sed -i -e 's,github.com/my/project,github.com/my/project/v2,g' {} \;
$

4.现在我们拥有了v2 version,如果想要在发布前测试可以先打预发布的tag

$ git tag v2.0.0-alpha.1
$ git push origin v2.0.0-alpha.1
$

5.确定满意后可以发布v2版本

$ git tag v2.0.0
$ git push origin v2.0.0
$

参考文章:
part1 https://blog.golang.org/using-go-modules
part2 https://blog.golang.org/migrating-to-go-modules
https://blog.golang.org/publishing-go-modules
https://blog.golang.org/v2-go-modules

你可能感兴趣的:(Go语言)