vgoを試してみる

Go1.11から導入されるvgoを試してみたメモ書きです。

基本的な流れは、和訳: A Tour of Versioned Go (vgo) (Go & Versioning, Part2)に沿っています。versioningが必要な理由や議論などは本記事では扱いません。

上記記事からvgoの開発が進みコマンドがいくつか変更になっていたので、同じくvgoを試す方の一助となればと思います。 今後も変更が入る可能性がありますが、x/vgoからgo本体にマージされたので、いい区切りかと思い、記事としてまとめることにしました。

環境

❯ vgo version
go version go1.10.3 darwin/amd64 go:2018-02-20.1

vgoのインストール

❯ go get -u golang.org/x/vgo

vgoを動かしてみる

サンプルプログラム

// hello.go
package main // import "github.com/you/hello"

import (
    "fmt"

    "rsc.io/quote" // この時点では、cannot find packageになるけどvgoが解決してくれる
)

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

あとは何も書いていないgo.modも作っておく。

touch go.mod

vgo build

❯ vgo build
vgo: resolving import "rsc.io/quote"
vgo: finding rsc.io/quote v1.5.2
vgo: finding rsc.io/quote (latest)
vgo: adding rsc.io/quote v1.5.2
vgo: finding rsc.io/sampler v1.3.0
vgo: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
vgo: downloading rsc.io/quote v1.5.2
vgo: downloading rsc.io/sampler v1.3.0
vgo: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c

これでbuildされるので、実行してみる。

❯ ./hello
こんにちは世界。

空だったgo.modにも追記されている。

// go.mod
module github.com/you/hello

require rsc.io/quote v1.5.2

依存しているモジュールをvgo list -mで表示できる。
コマンドが変更になったので、vgo list -mだと1個しか出てこない。
vgo list -m allで全部出てくる。

❯ vgo list -m all
github.com/you/hello
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0

Upgrade

-uオプションでupdated packageを確認できる。コマンドが変わって[]内にLATESTが表示されるようになった。

❯ vgo list -u -m all
vgo: finding golang.org/x/text v0.3.0
vgo: finding rsc.io/sampler v1.99.99
github.com/you/hello
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c [v0.3.0]
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0 [v1.99.99]

golang.org/x/textをUpgradeしてみる。

❯ vgo get golang.org/x/text
vgo: downloading golang.org/x/text v0.3.0

go.modが変わっている。

❯ git diff go.mod
diff --git a/go.mod b/go.mod
index 3200210..6246735 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,6 @@
 module github.com/you/hello

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

listで見ても以下のようにv0.0.0-20170915032832-14c0d48ead0cからv0.3.0になっていることがわかる。

❯ vgo list -m all
github.com/you/hello
golang.org/x/text v0.3.0
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0

テストしてみる。

❯ vgo test all
?       github.com/you/hello    0.016s [no test files]
?       golang.org/x/text/internal/gen  0.078s [no test files]
ok      golang.org/x/text/internal/tag  0.011s
?       golang.org/x/text/internal/testtext 0.043s [no test files]
ok      golang.org/x/text/internal/ucd  0.015s
ok      golang.org/x/text/language  0.073s
ok      golang.org/x/text/unicode/cldr  0.132s
ok      rsc.io/quote    0.015s
ok      rsc.io/sampler  0.013s

rsc.io/quotev1.5.2には以下のようにバグがあるが、上記のようにokとなる。 これは、allの意味が"今の module 中の全てのパッケージと、それらが再帰的に import している全てのパッケージ"だから。

❯ vgo test rsc.io/quote/...
ok      rsc.io/quote    (cached)
--- FAIL: Test (0.00s)
    buggy_test.go:10: buggy!
FAIL
FAIL    rsc.io/quote/buggy  0.008s

vgo get -uですべてのmoduleをupgradeできる。

❯ vgo get -u
vgo: finding rsc.io/quote latest
vgo: finding golang.org/x/text latest
vgo: finding rsc.io/sampler latest
vgo: finding golang.org/x/text latest
vgo: finding rsc.io/sampler latest

rsc.io/samplerv1.99.99にupgradeされた。

❯ vgo list -m all
github.com/you/hello
golang.org/x/text v0.3.0
rsc.io/quote v1.5.2
rsc.io/sampler v1.99.99

でもテストには失敗する。

❯ vgo test all
vgo: downloading rsc.io/sampler v1.99.99
?       github.com/you/hello    0.016s [no test files]
?       golang.org/x/text/internal/gen  0.032s [no test files]
ok      golang.org/x/text/internal/tag  (cached)
?       golang.org/x/text/internal/testtext 0.020s [no test files]
ok      golang.org/x/text/internal/ucd  (cached)
ok      golang.org/x/text/language  (cached)
ok      golang.org/x/text/unicode/cldr  (cached)
--- FAIL: TestHello (0.00s)
    quote_test.go:19: Hello() = "99 bottles of beer on the wall, 99 bottles of beer, ...", want "Hello, world."
FAIL
FAIL    rsc.io/quote    0.014s
--- FAIL: TestHello (0.00s)
    hello_test.go:31: Hello([en-US fr]) = "99 bottles of beer on the wall, 99 bottles of beer, ...", want "Hello, world."
    hello_test.go:31: Hello([fr en-US]) = "99 bottles of beer on the wall, 99 bottles of beer, ...", want "Bonjour le monde."
FAIL
FAIL    rsc.io/sampler  0.014s

Downgrade

v1.99.99へUpgradeしたらテストに失敗してしまったので、Downgradeして戻すことにする。 戻せるバージョンに何があるのか確認。

❯ vgo list -m -versions all
github.com/you/hello
golang.org/x/text v0.1.0 v0.2.0 v0.3.0
rsc.io/quote v1.0.0 v1.1.0 v1.2.0 v1.2.1 v1.3.0 v1.4.0 v1.5.0 v1.5.1 v1.5.2 v1.5.3-pre1
rsc.io/sampler v1.0.0 v1.2.0 v1.2.1 v1.3.0 v1.3.1 v1.99.99

rsc.io/samplerを一つ前のversionv1.3.1へ戻す。

❯ vgo get rsc.io/sampler@v1.3.1
vgo: finding rsc.io/sampler v1.3.1
vgo: downloading rsc.io/sampler v1.3.1

rsc.io/samplerv1.99.99からv1.3.1にdowngradeされた。

❯ git diff go.mod
diff --git a/go.mod b/go.mod
index 6246735..a62aa4e 100644
--- a/go.mod
+++ b/go.mod
@@ -3,4 +3,5 @@ module github.com/you/hello
 require (
        golang.org/x/text v0.3.0
        rsc.io/quote v1.5.2
+       rsc.io/sampler v1.3.1
 )

ちゃんとテストも通る。

❯ vgo test all
?       github.com/you/hello    0.021s [no test files]
?       golang.org/x/text/internal/gen  0.020s [no test files]
ok      golang.org/x/text/internal/tag  (cached)
?       golang.org/x/text/internal/testtext 0.031s [no test files]
ok      golang.org/x/text/internal/ucd  (cached)
ok      golang.org/x/text/language  (cached)
ok      golang.org/x/text/unicode/cldr  (cached)
ok      rsc.io/quote    0.016s
ok      rsc.io/sampler  0.015s

もっと前のversionv.1.2.0にすることもできる。 rsc.io/quoteも依存しているので一緒にdowngradeする必要がある。

❯ vgo get rsc.io/sampler@v1.2.0
vgo: finding rsc.io/sampler v1.2.0
vgo: finding rsc.io/quote v1.5.1
vgo: finding rsc.io/quote v1.5.0
vgo: finding rsc.io/quote v1.4.0
vgo: finding rsc.io/sampler v1.0.0
vgo: downloading rsc.io/sampler v1.2.0

ただし、テストに失敗する。

❯ vgo test all
vgo: downloading rsc.io/quote v1.4.0
?       github.com/you/hello    0.019s [no test files]
?       golang.org/x/text/internal/gen  0.023s [no test files]
ok      golang.org/x/text/internal/tag  (cached)
?       golang.org/x/text/internal/testtext 0.035s [no test files]
ok      golang.org/x/text/internal/ucd  (cached)
ok      golang.org/x/text/language  (cached)
ok      golang.org/x/text/unicode/cldr  (cached)
--- FAIL: TestHello (0.00s)
    quote_test.go:12: Hello() = "こんにちは世界。", want "Hello, world."
FAIL
FAIL    rsc.io/quote    0.017s
--- FAIL: TestHello (0.00s)
    hello_test.go:31: Hello([fr en-US]) = "Bonjour le monde.", want "Bonjour la monde."
FAIL
FAIL    rsc.io/sampler  0.012s

noneで依存しているモジュールをすべて削除できる。

❯ vgo get rsc.io/sampler@none
vgo: finding rsc.io/quote v1.3.0

こうするとテストが通る(全然モジュールが残っていないけど)。

❯ vgo test all
vgo: downloading rsc.io/quote v1.3.0
?       github.com/you/hello    0.009s [no test files]
ok      rsc.io/quote    0.009s

Exclude

v1.99.99がうまく動かないことを記録したい。

事前準備として、最新化しておく。

❯ vgo get -u
vgo: finding rsc.io/quote latest
vgo: finding golang.org/x/text latest
vgo: finding rsc.io/quote latest
vgo: finding rsc.io/sampler latest
vgo: finding golang.org/x/text latest
vgo: finding rsc.io/sampler latest

たしかにv1.99.99になっている。

❯ vgo list -m all
github.com/you/hello
golang.org/x/text v0.3.0
rsc.io/quote v1.5.2
rsc.io/sampler v1.99.99

go.modexclude "rsc.io/sampler" v1.99.99を追加すればよい。
合わせてgo.modrsc.io/sampler v1.3.1にするのも忘れずに。

❯ vgo list -m all
github.com/you/hello
golang.org/x/text v0.3.0
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.1

ちなみに、rsc.io/sampler v1.3.1にするのも忘れると以下のようにエラーになってくれるのでちゃんとExcludeされている。

❯ vgo get -u
vgo: github.com/you/hello() depends on excluded rsc.io/sampler(v1.99.99) with no newer version available

これでテストが通る。

❯ vgo test all
?       github.com/you/hello    0.016s [no test files]
?       golang.org/x/text/internal/gen  0.021s [no test files]
ok      golang.org/x/text/internal/tag  (cached)
?       golang.org/x/text/internal/testtext 0.021s [no test files]
ok      golang.org/x/text/internal/ucd  (cached)
ok      golang.org/x/text/language  (cached)
ok      golang.org/x/text/unicode/cldr  (cached)
ok      rsc.io/quote    (cached)
ok      rsc.io/sampler  (cached)

Replace

依存していたrsc.io/quoteを置き換えてみる。

❯ git clone https://github.com/rsc/quote ../quote

../quote/quote.goを以下のように書き換える。

// Hello returns a greeting.
func Hello() string {
    // return sampler.Hello() // これを消して
    return sampler.Glass() // こっちを追加
}

go.modの末尾にreplace "rsc.io/quote" v1.5.2 => "../quote"追記する。 すると以下のようにreplaceされていることが確認できる。

❯ vgo list -m all
github.com/you/hello
golang.org/x/text v0.3.0
rsc.io/quote v1.5.2 => ../quote
rsc.io/sampler v1.3.1

buildして実行する。

❯ vgo build

❯ ./hello
私はガラスを食べられます。それは私を傷つけません。

references