Go Modules 如何创建和发布 v2 及更高版本?

简介: Go Modules 如何创建和发布 v2 及更高版本?

640.jpg

01

介绍


随着一个成功的项目的逐渐成熟和新需求的添加,过去的功能和设计决策可能会失去意义。开发人员可能希望整合通过删除已弃用函数学到的经验教训,重命名类型,或将复杂的包拆分为可管理的部分。这些类型的更改,需要下游用户努力将代码迁移到新的 API,因此,不应在没有仔细考虑其收益是否大于成本的情况下做出这些更改。


对于仍在试验的项目 (在主要版本 v0) 中,用户预计偶尔会发生重大更改。对于被宣布为稳定版本的项目(在主要版本 v1 或更高版本中),必须在新的主要版本中完成重大更改。本文将探讨主要版本语义、如何创建和发布新的主要版本,以及如何维护模块的多个主要版本。


02

主要版本和模块路径


在 Go 语言中,模块有一个重要原则,导入兼容性规则:

如果旧包和新包具有相同的导入路径,则新包必须与旧包向后兼容。


根据定义,如果新的主要版本的包与以前的版本不向后兼容。这意味着模块的新主要版本必须具有与以前版本的不同的模块路径。从 v2 开始,主要版本必须出现在模块路径的末尾(在 go.mod 文件中的模块语句中声明)。


例如,当模块的作者开发

github.com/googleapis/gax-go 的 v2 时,

他们使用新的模块路径

github.com/googleapis/gax-go/v2。想要使用 v2 的用户必须更改其包导入和模块要求,改为

github.com/googleapis/gax-go/v2。


对主要版本的后缀要求是 Go Modules 与大多数其他依赖项管理工具不同的方法之一。解决依赖性问题需要后缀。


在 Go 模块 gopkg.in 允许包维护者遵循我们现在所说的导入兼容性规则。使用 gopkg.in,如果依赖于导入 gopkg.in/yaml.v1 的包和导入 gopkg.in/yaml.v2 的另一个包,则没有冲突,因为两个 yaml 包具有不同的导入路径 - 它们使用版本后缀,就像使用 Go 模块一样。


由于 gopkg.in 与 Go Modules 共享相同的版本后缀方法,因此 Go 命令接受 gopkg.in/yaml.v2 中的 .v2 作为有效的主要版本后缀。这是与计算机兼容的特殊情况:gopkg.in 域中的模块需要一个斜杠后缀,如 /v2。


03

主要版本策略


建议的策略是在以主要版本后缀命名的目录中开发 v2+ 模块。


github.com/googleapis/gax-go @ master branch
/go.mod    → module github.com/googleapis/gax-go
/v2/go.mod → module github.com/googleapis/gax-go/v2


此方法与不支持模块的依赖管理工具兼容:存储库中的文件路径与 GoPATH 模式下所需的路径相匹配。此策略还允许在不同目录中一起开发所有主要版本。


其他策略可能将主要版本保留在单独的分支上。但是,如果 v2+ 源代码位于存储库的默认分支(通常是主分支)上,则不具有版本识别功能的工具(包括 GOPATH 模式下的 go 命令)可能无法区分主要版本。


本文中的示例将遵循主要版本子目录策略,因为它提供了最大的兼容性。如果他们有用户在 GOPATH 模式下开发,我们建议模块作者遵循此策略。


04

发布 v2 及更高版本


本文使用 github.com/googleapis/gax-go 作为示例:


$ pwd
/tmp/gax-go
$ ls
CODE_OF_CONDUCT.md  call_option.go  internal
CONTRIBUTING.md     gax.go          invoke.go
LICENSE             go.mod          tools.go
README.md           go.sum          RELEASING.md
header.go
$ cat go.mod
module github.com/googleapis/gax-go
go 1.9
require (
    github.com/golang/protobuf v1.3.1
    golang.org/x/exp v0.0.0-20190221220918-438050ddec5e
    golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3
    golang.org/x/tools v0.0.0-20190114222345-bf090417da8b
    google.golang.org/grpc v1.19.0
    honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099
)
$


为了开始开发 github.com/googleapis/gax-go 的 v2,我们将创建一个新的 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
$


现在,让我们通过复制当前 go.mod 文件并添加 v2/ 后缀到模块路径来创建一个 v2 go.mod 文件:


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


请注意,v2 版本被视为 v0 / v1 版本的单独模块:两者可能共存于同一版本。因此,如果您的 v2+ 模块有多个包,您应该更新它们以使用新的 /v2 导入路径:否则,您的 v2+ 模块将依赖于您的 v0 / v1 模块。例如,若要更新对github.com/my/project 的所有 github.com/my/project/v2,可以使用 find 和 sed:


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


现在我们有了一个 v2 模块,但是我们想在发布发行版之前进行试验并进行更改。在发布 v2.0.0(或没有预发布后缀的任何版本)之前,我们可以在决定使用新 API 时进行开发并进行重大更改。如果我们希望用户能够在正式稳定新API 之前对其进行试验,则可以发布 v2 预发行版本:


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


一旦我们对 v2 API 感到满意并且确定我们不需要任何其他重大更改,就可以标记 v2.0.0:


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


此时,有两个主要版本需要维护。向后兼容的更改和错误修复将导致新的次要版本和修补程序版本(例如v1.1.0,v2.0.1等)。


05

总结


主要版本更改会导致开发和维护的开销,并且需要下游用户的支持才能进行迁移。项目越大,这些开发和维护的开销往往越大。只有在确定了令人信服的理由之后,才进行主要版本更改。一旦确定了令人信服的重大变更原因,我们建议在 master 分支中开发多个主要版本,因为它需要与各种现有依赖管理工具兼容。


对 v1+ 模块的重大更改应始终在新的 vN+1 模块中进行。发布新模块时,对于维护人员和需要迁移到新软件包的用户来说意味着更多的工作。因此,维护人员应在发布稳定版本之前验证其 API,并仔细考虑在 v1 之后是否确实需要进行重大更改。





目录
相关文章
|
5月前
|
Dubbo 应用服务中间件 API
Go语言微服务框架重磅升级:dubbo-go v3.2.0 -alpha 版本预览
随着 Dubbo3 在云原生微服务方向的快速发展,Dubbo 的 go 语言实现迎来了 Dubbo3 版本以来最全面、最大幅度的一次升级,这次升级是全方位的,涉及 API、协议、流量管控、可观测能力等。
|
7月前
|
存储 Go API
怎么发布 Go Modules v1 版本?
怎么发布 Go Modules v1 版本?
35 0
|
6月前
|
Shell Go 网络安全
openssl 证书生成笔记(go 1.15版本以上)
openssl 证书生成笔记(go 1.15版本以上)
|
7月前
|
缓存 JSON Go
Go 语言各个版本支持 Go Modules 的演进史
Go 语言各个版本支持 Go Modules 的演进史
47 1
|
7月前
|
资源调度 Kubernetes Go
SchedulerX支持Go版本SDK
Go语言越来越流行,SchedulerX是阿里云的分布式任务调度服务,新增支持Go版本SDK
64 0
|
10月前
|
Shell Go 网络安全
openssl 证书生成学习笔记(go 1.15版本以上) | 周末学习
golang 1.15+版本上,用 gRPC通过TLS实现数据传输加密时,会报错证书的问题
118 0
openssl 证书生成学习笔记(go 1.15版本以上) | 周末学习
|
11月前
|
缓存 Java 编译器
Go语言10年版本演进(2012.03~2022.03)
Go语言10年版本演进(2012.03~2022.03)
46 0
Go语言10年版本演进(2012.03~2022.03)
|
11月前
|
Go API 开发工具
Go Module 语义化版本规范
Go Module 语义化版本规范
Golang:go-version一个对语义化版本进行解析、比较的库
Golang:go-version一个对语义化版本进行解析、比较的库
103 0