Go 1.11 からはじめるプロジェクトでは、パッケージマネージャは dep ではなく go mod(Go Modules) を使おう

go mod(Go Modules) がこれからのスタンダード

Go を使いはじめるにあたってパッケージマネージャを探した時の話。ghq や glide といった過去の遺産に加えて godep, dep (ややこしい) と百花繚乱な様子が窺え、初見では、将来的に何が天下統一してくれるのか、わからずじまいだった。公式で紹介されている dep を使えばいいのかな、と会社の同僚に相談したところ dep すらももう古くて、go mod(Go Modules) がこれからのスタンダードになるという話だった。

確かに dep のページでも "official experiment." と明記されている。

github.com

正式採用された go mod(Go Modules) と過去のツールたち

パッケージマネージャとして Go Module(GO111MODULE) のプロポーザルが正式に受け入れられたことと、過去の実験的な試行(GO15VENDOREXPERIMENT)として百花繚乱のツール群が紹介されている。

PackageManagementTools · golang/go Wiki · GitHub

Go 1.11 から go mod が試験的に組み込まれ、1.13 で完全に組み込まれるとのこと。vgo はあくまで go mod のプロトタイプなので 1.11 からは使う必要がない。

Modules · golang/go Wiki · GitHub

Go 1.11 からはじめるプロジェクトでは dep ではなく go mod(Go Modules) を使おう、という議論

github.com

まだ dep を使っていないプロジェクトで 1.11 から開発をはじめる場合dep を使う意味はほとんどありません。
dep は様々な問題を抱えており将来的には使われなくなるので、そこに学習の時間を割くのは避けた方がいいでしょう。
新しく 1.11 から開発をはじめるのであれば、dep ではなく Go modules を使いましょう。

Kubernetes プロジェクトも dep は完全に飛ばして godep から Go modules への移行を計画しています
(godep -> dep はダメだったので godep -> go modules へ移行予定)。
当初 Kubernetes プロジェクトは godep から dep への移行を検討したものの結局うまくいかなかったのです。

go mod の使い方

https://github.com/golang/go/wiki/Modules#quick-start

go mod init してから go build するとライブラリが自動的にダウンロードされて $GOPATH/pkg に格納される。この点は sbt build と似ている。ソースの中で使用されている外部ライブラリが検出され go.mod と go.sum という二つのファイルが生成されるが、go.mod がバージョン情報を記録するファイルで go.sum はその生情報となっている。外部ライブラリのバージョンを更新したい場合は go.mod を編集した後に go build し直す、という流れになる。私は Ruby ユーザなので go.mod = Gemfile, go.sum = Gemfile.lock というようなイメージで捉えている。 ₍₍(ง˘ω˘)ว⁾⁾

$ cd $GOPATH && mkdir hello && cd hello
$ pwd
/home/kyagi/lab/go/hello 
$ vi hello.go

$ go mod init github.com/kyagi/hello/
go: creating new go.mod: module github.com/kyagi/hello/

$ go build
go: finding rsc.io/quote v1.5.2
go: downloading rsc.io/quote v1.5.2
go: finding rsc.io/sampler v1.3.0
go: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: downloading rsc.io/sampler v1.3.0
go: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c

$ find $GOPATH/pkg/mod | grep quote
/home/kyagi/lab/go/pkg/mod/cache/download/rsc.io/quote
/home/kyagi/lab/go/pkg/mod/cache/download/rsc.io/quote/@v
/home/kyagi/lab/go/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
(... snip ...)

$ ls
go.mod  go.sum  hello.go

$ cat go.mod
module github.com/kyagi/hello/

require (
    rsc.io/quote v1.5.2
)

$ 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 run hello.go
Hello, world.

GOPATH のいままでとこれから

GO111MODULE になると、$GOPATH は go build 時に $GOPATH/pkg/mod に必要なライブラリがダウンロードされるだけの役割になる、と個人的に理解している。つまり $GOPATH はほとんどシステム的なライブラリ置き場になる(Ruby でいう .gem や Scala でいう .ivy2 に近い役割のディレクトリ)。これに伴ってプロジェクトのディレクトリも GO111MODULE 以前に推奨されていた $GOPATH/src/ ではなく、どこにおいてもいいという認識でいる。

いままで) $GOPATH/src/sandbox で開発をすることが推奨されていた
これから) どこで開発をしてもよい(/tmp/sandbox でも $HOME/lab/sandbox でも)。go build 時に go.mod で指定しているライブラリは $GOPATH/pkg/mod にダウンロード(キャッシュ)される

プロジェクトのディレクトリをどこにおいてもよく(どこで開発してもよく)、GOPATH は go get 時に $GOPATH/src に、 go build 時に $GOPATH/pkg/mod 配下にライブラリがダウンロードされるキャッシュ置き場としての役割になったので、個人環境の設定は以下のように変更している。

いままで) export GOPATH="$HOME/lab/go"
これから) export GOPATH="$HOME/.go"

※そもそも SRE 的な立場でしか Go を触っていないので間違っていたらご指摘いただけるとありがたいです。 (´・ω・`)