Go mod的使用、发布、升级

目录

简介

这篇文章介绍了go模块管理的基础使用,分以下三个部分

  1. 创建模块
  2. 发布模块及版本介绍
  3. 版本升级

信息

本文是阅读go blog之后的一个提炼,更详细文档请参考 Go Modules . https://blog.golang.org/using-go-modules

创建模块

创建目录和源代码1

$GOPATH/src之外创建一个目录hello,然后新增两个文件hello.gohello_test.go,项目结构如下

1
2
3
.
├── hello.go
└── hello_test.go 

分别编辑hello.gohello_test.go

1
2
3
4
5
6
// hello.go
package hello

func Hello() string {
    return "Hello, world."
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// hello_test.go
package hello

import "testing"

func TestHello(t *testing.T) {
    want := "Hello, world."
    if got := Hello(); got != want {
        t.Errorf("Hello() = %q, want %q", got, want)
    }
}

初始化mod

可以在当前目录下执行 go test 看到执行出错,由于我们的项目不在$GOPATH中,所以go command不知道当前目录的导入路径;可以使用 go mod init 命令是当前目录变成模块的根目录

1
2
go mod init github.com/youdw/hello
go: creating new go.mod: module github.com/youdw/hello

技巧

注意模块命名方式,如果你的项目要发布到github,则命名为:github.com/<USERNAME>/<MODULE_NAME> e.g.github.com/youdw/hello
此时再执行go test,可以看到已经成功执行。

1
2
3
go test
PASS
ok  	github.com/youdw/hello	0.020s

至此hello模块已经初始化完成,让我们看下现在的目录结构

1
2
3
4
5
.
├── go.mod
├── go.sum
├── hello.go
└── hello_test.go

版本号及发布 2

Go模块版本只要分为三个部分如<major>.<minor>.<patch>,例如对于v1.0.1,主版本<major>是1,次版本<minor>是0,补丁版本<patch>是1

v0版本为项目的初始版本,版本不保证稳定行,可以通过git tag来标记版本,将tag推送至仓库即可 v1版本为稳定版本,当你的项目稳定之后,可以标记v1版本对外发布;另外对于稳定之后的预发布版本,由于Go命令首选的是正常版本,而不是预发布版本;可以通过-来制定预发布版本,如v1.0.1-betav1.0.1-alpha;使用的时候需要显示的指定预发布版本go get github.com/youdw/helle@v1.0.1-beta 下面看下怎么发布第一个v0.0.1版本

创建仓库

首先在你的github仓库创建一个repository,命名为hello,然后将hello项目同步至仓库

标记并推送Tag

通过git标签维护版本

1
2
    git tag v0.0.1
    git push origin v0.0.1

在其他项目中引用

在项目中直接导入"github.com/youdw/hello",然后通过执行 go mod tiny或者go mod build就可以添加新的依赖了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package main

import (
	"fmt"
	"github.com/youdw/hello"
)

func main()  {
	fmt.Println(hello.Hello())
}

引入依赖之后 cat go.mod,可以看到已经引入了我们自定义的模块

1
2
3
4
5
6
7
8
module study

go 1.13

require (
        github.com/youdw/hello v0.0.1
)

版本升级

Go模块中规范了一个重要原则

If an old package and a new package have the same import path, the new package must be backwards compatible with the old package.3

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

v0->v1

假设我们自定义的模块已经稳定了,那么开始要对外发布v1.0.0版本了

  1. 拉取新的分支v1.0.0_branch
  2. git tag v1.0.0 并且推送到远程仓库

v1->v2

v1->v2的升级属于主版本的升级(v2不向后兼容), 这里有两种方式:

  • 创建新的版本目录v2
  • 继续使用v0->v1的升级方式

创建新的版本目录v2

按照go模块规范的原则,我们不能继续使用github.com/youdw/hello 这个包路径了。当前v1版本目录如下;

1
2
3
4
5
.
├── go.mod
├── go.sum
├── hello.go
└── hello_test.go

为了开始开发v2,在hello目录下创建v2目录,然后把.go 和 mod 文件复制到v24 ,然后将v2目录下的mod路径修改为 github.com/youdw/hello/v2

1
2
3
4
mkdir v2
cp *.go v2/
cp go.mod v2/go.mod
go mod edit -module github.com/youdw/hello/v2 v2/go.mod

完成之后的项目结构如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
.
├── go.mod
├── go.sum
├── hello.go
├── hello_test.go
└── v2
    ├── go.mod
    ├── hello.go
    └── hello_test.go

1 directory, 7 files

发布v2

1
2
git tag v2.0.0
git push origin v2.0.0

继续使用v0->v1的升级方式

拉取新的分支,修改go.mod路径为github.com/youdw/hello/v2,基于master分支打tag v2.0.0

1
2
3
4
go mod edit -module github.com/youdw/hello/v2
git push
git tag v2.0.0
git push origin v2.0.0

以上两种方式,第一种是go模块推荐的方式,但是维护和开发的开销较大,

参考

- [1] [using-go-modules](https://blog.golang.org/using-go-modules)
- [2] [publishing-go-modules](https://blog.golang.org/publishing-go-modules)
- [3] [Semantic Import Versioning](https://research.swtch.com/vgo-import)
- [4] [v2-go-modules](https://blog.golang.org/v2-go-modules)