注意
ここの記事で書かれている操作は、 https://github.com/golang/go/issues/24917 で報告した https://github.com/ory/fosite-example をvgoでビルドしようとして検証しています。
利用したvgo
golang.org/x/vgo
の203abfb0741bf96c7c5e8dab019f6fe9c89bded3
の時点でgo get -u golang.org/x/vgo
したものgo version go1.10.2 darwin/amd64 vgo:2018-02-20.1
TL;DL
思った通りの状態にならない。
ライブラリ作者全員semverで殴って回る必要がある。
ログから情報が得られない。
実行もクソ遅い。
ゆえに辛い。
まずはじめに
Goユーザは $GOPATH
の中で生きている。
アプリケーションのパッケージ管理のため、vendoringの仕組みができた。
パッケージマネージャとしてgbとかdepとか色々なものがあった。
あったけど、最終的にgoコマンドに組み込みとなる、最終的なパッケージ管理の仕組みが生まれようとしている。
vgoだ。
今はvgoという名前だけど、最終的にはgoに組み込まれる(はずだ)。
このproposalは既にacceptedになっていて、未来は確定しつつあります。
この記事ではこれ以上のvgoについての説明を行わない。
詳しく知りたい人は、Go & Versioning[和訳]を読むといいだろう。
vgoのここが良い!
まずは良いところを。
$GOPATH
free
プロジェクトを配置する場所が $GOPATH
配下に限定されなくなります。
好きな場所に置いてよい!やったー!
SemVerの採用とタグベースの運用
Goもsemverで運用されていきます。
何かしら更新があれば、gitでtagを打ちpushされる世界になるでしょう。
この文化が浸透すれば、依存しているライブラリのバージョンアップは非常に容易な作業になっていくでしょう。
npmにpublishしているユーザがみんなお行儀よくなっていったように、Goコミュニティもsemverに慣れていくでしょう。
同一ライブラリの異なるバージョンへの依存への(文化的)解決
複数のライブラリを使う場合、依存関係的には孫にあたるライブラリが重複し、かつ異なるバージョンを参照したい場合があります。
これは、今までの単層のvendoringでは難しかったのですが、これに対して github.com/vvakame/hoge/v1
と github.com/vvakame/hoge/v2
に分けておけばいいじゃない という斜め上の解決が行われました。
斜め上といえば斜め上なんですが、旧バージョンについてもpatchを受け付けられるとか、管理がしやすくなるという点で良いこともあります。
素直に読むと、リポジトリのrootに置いてあるコードは互換性のためにずっと残しておけ、みたいなことを言っててヤベーこと言いよる…という気持ちです。
でもまぁこれは v0
を切って、最初はそこで開発するなどの開発者側のワークアラウンドでなんとかなるレベルかもしれません。
あとは、エディタがpackage内でちぐはぐなバージョンを自動的にimportしないように気をつける必要があります(つらそう
goコマンドに組み込み
単にgit cloneして、 vgo test all
とかすれば、依存ライブラリを自動的に取ってきてくれて動きはじめる!
ライブラリ追加したければ vgo get go.mercari.io/datastore
とかやるだけ!
すごい!楽!わかりやすい!初心者の味方!
vgoのここがヤバい
ついでやばいところを述べていきます。
中途半端にタグがついているリポジトリ
google.golang.org/appengine
はアクティブに開発されているリポジトリだが、2016年に v1.0.0
タグが切られ、その後は何もない。
vgo(やdep)で単純に google.golang.org/appengine
を追加すると、2年も前のリビジョンを使わされてしまう!
辛いですね。
この問題はライブラリ作者全員がヤル気を出し、ちゃんとタグをつける運用を開始したら解決されます。
ライブラリ作者全員をsemverで叩いて回りましょう。例
使えない master/HEAD
上記の問題を解消するには、 vgo get google.golang.org/appengine@master
を実行すれば…。
と思いきや、コレでもダメで、 v1.0.0
にされてしまいます。vgo get google.golang.org/appengine@b1f26356af11148e710935ed1ac8a7f5702c7612
も同様。go.mod
中の require
を google.golang.org/appengine master
に書き換えて vgo get -u
しても v1.0.0
に戻される…。
どうすればいいんですかね…?
なにがどうなってどう go.mod
が書き換わったのか、というのがログから全く読み取れない…。
気持ちよく動いてる間は便利なのかもしれないけど、意図通りにならない時に完全にブラックボックス化していて辛い。
しかもこのブラックボックスは将来的に go
本体に組み込まれてしまい回避不可能になるんだぜ…。
この問題はライブラリ作者全員がヤル気を出し、ちゃんとタグをつける運用を開始したら(masterを使いたいという欲求がなくなるので)解決されます。
いつの間にか巻き戻るバージョン、消えるパッケージ
vgo get google.golang.org/appengine@master
すると何故か require に書かれるパッケージが減ります。
1 | diff --git a/go.mod b/go.mod |
なんでやねん。google.golang.org/appengine
は変わってないくせに…。
何がどうなってこうなったのかはログからは全くわかりません。
本当に最新なのかわからない vgo list -m -u
1 | $ vgo list -m -u |
上から順に見てVERSIONがくっそ古い jwt-go を適当に見に行ってみました。
最新はv3.2.0です。
確かに、 ^1.0.0
の範囲だと v1.0.2
は LATESTなんですが、プロジェクトを健全に保つために知りたいLATESTは v3.2.0
だと思います。vgo get github.com/dgrijalva/jwt-go
しても v3.2.0
にはなりません。vgo get github.com/dgrijalva/jwt-go@v3
してみたら go.mod から jwt-go が消えました。
一体全体どういうことだってばよ…。
何がどうなってこうなったのかはログからは全くわかりません。
ひたすらに遅いコマンド類
1 | $ time vgo list -m -u |
何回も実行した上でコレです。
初めて vgo get google.golang.org/appengine@master
を実行した時はカップラーメンのためにお湯を沸かしてお湯入れて待って食べてSplatoon2起動するぐらいの時間がかかりました。
まとめ
この中で何が起こってるかもよくわからず --help
でロクな情報が得られないシステム、誰が使えるの???
ストレスでハゲそう。
この記事は社内Slackでクダをまいてたらそれを#4 Open Go Fridayで話せと @tenntenn さんに言われたので書かれました。