go mod 使用

简介

go 1.11以后提供了新的管理依赖的方式, 使得管理依赖,尤其是依赖版本更加的明确且易于管理, 这种方式就是go mod

在项目的根目录有个go.mod的文件, 文件的内容是所有依赖的go package的集合, 以文件树的形式存在.
文件中中明确的说明了go所有依赖的路径及版本

配置

# 这三个路径一直存在
export GOPATH=$HOME/go
export GOROOT=/usr/local/go
export GOBIN=$GOPATH/bin
# 支持 go mod 需要配置如下两个选项
# 开启go mod
export GO111MODULE=on
# 配置go mod使用的依赖库代理服务器
export GOPROXY=https://goproxy.io

创建一个新的go mod

package hello
import "rsc.io/quote"
func Hello() string {
    return quote.Hello()
}

# write a test file
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)
    }
}

执行初始化命令

$ go mod init example.com/hello

查看生成的go.mod, 执行完初始化后, 在项目的根目录有go.mod文件生成

$ cat go.mod
module example.com/hello

go 1.13

执行go test

[~/go/src/hello]$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: 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
go: finding rsc.io/sampler v1.3.0
go: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
PASS
ok      example.com/hello   0.008s

再次查看go.mod文件

module example.com/hello

go 1.13

require rsc.io/quote v1.5.2

自动增加了 我们依赖的rsc.io/quote 目录
查看我们依赖的module

[~/go/src/hello]$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的文件, 引用模块的hash值
查看go.sum文件,

[~/go/src/hello]$cat go.sum 
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

更新go mod 依赖的版本

go get golang.org/x/text
go: finding golang.org/x/text v0.3.0
go: downloading golang.org/x/text v0.3.0
go: extracting golang.org/x/text v0.3.0
$ go test
PASS
ok      example.com/hello   0.013s

自动更新

$ go list -m all
example.com/hello
golang.org/x/text v0.3.0
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0
$ cat go.mod
module example.com/hello

go 1.12

require (
    golang.org/x/text v0.3.0 // indirect
    rsc.io/quote v1.5.2
)
$

更新sampler 试一试

go get rsc.io/sampler
go: finding rsc.io/sampler v1.99.99
go: downloading rsc.io/sampler v1.99.99
go: extracting rsc.io/sampler v1.99.99
$ go test
--- FAIL: TestHello (0.00s)
    hello_test.go:8: Hello() = "99 bottles of beer on the wall, 99 bottles of beer, ...", want "Hello, world."
FAIL
exit status 1
FAIL    example.com/hello   0.014s
$

单测失败了, 说明最新的包和我们本地的代码已经不兼容了, 我们看看sampler的历史版本

$ go list -m -versions rsc.io/sampler
rsc.io/sampler v1.0.0 v1.2.0 v1.2.1 v1.3.0 v1.3.1 v1.99.99

我们回退到上一版本, v1.3.1 尝试一下

$ go get rsc.io/[email protected]
go: finding rsc.io/sampler v1.3.1
go: downloading rsc.io/sampler v1.3.1
go: extracting rsc.io/sampler v1.3.1
$ go test
PASS
ok      example.com/hello   0.022s
$

添加一个新版本的依赖

我们升级一下 "rsc.io/quote" 升级为 "rsc.io/quote/v3"

package hello

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

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

增加新的test

func TestProverb(t *testing.T) {
    want := "Concurrency is not parallelism."
    if got := Proverb(); got != want {
        t.Errorf("Proverb() = %q, want %q", got, want)
    }
}

执行test

$go test
go: finding rsc.io/quote/v3 v3.1.0
go: downloading rsc.io/quote/v3 v3.1.0
go: extracting rsc.io/quote/v3 v3.1.0
PASS
ok      example.com/hello   0.006s

查看依赖的模块

$ go list -m rsc.io/q...
rsc.io/quote v1.5.2
rsc.io/quote/v3 v3.1.0
$

增量或者灰度迁移的能力在大型的程序中尤为重要

全部升级为新版本

查看新版本支持的API

$ 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
$

升级调用的函数

package hello

import quoteV3 "rsc.io/quote/v3"

func Hello() string {
    // 放弃使用旧版的接口, 改为V3的接口
    return quoteV3.HelloV3()
}

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

已经移除了旧版接口, 我们不在需要对V3做别名处理, 所以可以改成如下

package hello
import "rsc.io/quote/v3"
func Hello() string {
    return quote.HelloV3()
}
func Proverb() string {
    return quote.Concurrency()
}

查看依赖的版本

$go list -m all
example.com/hello
golang.org/x/text v0.3.2
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e
rsc.io/quote v1.5.2
rsc.io/quote/v3 v3.1.0
rsc.io/sampler v1.3.1

可以看到旧版我们都已经去除了, 但是没有移除, 需要go mod tidy了
go mod tidy 清楚我们不需要的模块

$go mod tidy
$go list -m all
example.com/hello
golang.org/x/text v0.3.2
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e
rsc.io/quote/v3 v3.1.0
rsc.io/sampler v1.3.1
$cat go.mod 
module example.com/hello

go 1.13

require (
    golang.org/x/text v0.3.2 // indirect
    rsc.io/quote/v3 v3.1.0
    rsc.io/sampler v1.3.1 // indirect
)

结论

  • go mod init 初始化一个新的module
  • go build, go test, 其它内置的包构建命令来更新我们需要的依赖到go.mod文件
  • go list -m all 列出我们当前所有依赖的module
  • go get 获取指定的升级版本
  • go mod tidy 更新操作, 去除不需要的依赖

引用

https://blog.golang.org/using-go-modules

你可能感兴趣的:(go mod 使用)