こんにちは! ソーシャルゲーム事業部の川添 (@acidlemon) です。
この記事は Tech KAYAC Advent Calendar Migration Trackの8日目です。 今年はみなさまどんな一年だったでしょうか。私もいろいろありましたが、最近ちょっと私がやってたマイグレーションというと自分の開発環境のGOPATHの掃除がありますので、今日はその話を書こうと思います。
2018年までのGOPATH
GOPATHというと、昔からGo言語をゴリゴリ書いていた人にはおなじみの、 GOPATH=$HOME/go
みたいなのを設定して、go get github.com/kayac/ecspresso
すると $GOPATH/src
の下に $GOPATH/src/github.com/kayac/ecspresso
みたいなディレクトリができてそこにソースコードがcloneされるみたいなやつです。
で、go modが主流になるまでは、go get github.com/kayac/ecspresso
を実行すると ecspresso が
依存するいろんなGoのパッケージ、たとえば github.com/aws/aws-sdk-go
、 github.com/mattn/go-isatty
、 github.com/morikuni/aec
、
github.com/Songmu/prompter
などなどが $GOPATH/src
の下にcloneされます。
……というのを数年やっていると、気がつくと $GOPATH/src
の下は大量のリポジトリであふれかえります。
ちょっと私の手元で du -h -d 2
してどのぐらい散らかっているか確認したのを一部抜粋すると
5.3M ./github.com/jinzhu 356K ./github.com/joho 3.8M ./github.com/stamblerre 316K ./github.com/cenkalti 1.3M ./github.com/sirupsen 29M ./github.com/sourcegraph 300K ./github.com/philhofer 1.2M ./github.com/soh335 1.1M ./github.com/go-martini 175M ./github.com/Microsoft 336K ./github.com/konsorten 4.3M ./github.com/Songmu 752K ./github.com/mholt 1.6M ./github.com/codegangsta 396K ./github.com/Azure 508K ./github.com/Masterminds 336K ./github.com/methane 380K ./github.com/mizkei 192M ./github.com/aws 972K ./github.com/nicksnyder 356K ./github.com/uudashr 768K ./github.com/BurntSushi 1.7M ./github.com/pkg 1.3M ./github.com/jmoiron 22M ./github.com/hiryma 6.5M ./github.com/ulikunitz 704K ./github.com/sebest 27G ./github.com/kayac 620K ./github.com/nsf 24M ./github.com/mattn 348K ./github.com/pborman 632K ./github.com/monochromegane 3.5M ./github.com/tdewolff
こんなような感じで大量のリポジトリで溢れています。まぁしかたないよね。
2019年のGOPATH
2019年はGo 1.12(2月)、Go 1.13(8月)のリリースがあり、Go Modulesの動作を標準でいい感じにする GO111MODULE
環境変数のデフォルト値 が auto
に設定されました。
元々きいてた話だと1.13からは on になって移行が促進されるような話だった気がしますが実際はautoのままで、GOPATHの下かどうかに関係なく基本的には go.mod があれば go get するときに module-aware modeになっているはずです(GOPATH以下のautoの挙動変更が1.13から入りました)。
module-aware modeだと、go getして一緒に降ってくる依存ライブラリは $GOPATH/pkg/mod
の下に入るようになりました。これによって、 $GOPATH/src
の下が散らからなくなりました。
また、地味にGOPATHモードと違ってgitをcloneするわけではないので $GOPATH/pkg/mod
の下には .git
ディレクトリが作られないため、今までよりもローカルディスクの使用量がエコになるわけです。
デフォルトでGo Modules環境に強制してしまう
Go 1.13からはgo envという環境変数を列挙するサブコマンドに -w
オプションが追加されて、 go env -w GO111MODULE=on
とやるとgoコマンドのデフォルトの環境変数を設定することが出来るようになりました。この設定は $HOME/.config/go/env
ファイルに保存されるようです。
ということで、これを実行すると、今後のgo get
などが全部基本module-aware modeになります。つまり、$GOPATH/src
の下にはいつのまにか依存でcloneされたディレクトリが生えた〜 みたいなことがなくなります。今こそ、$GOPATH/src
の掃除のときですね。
メキッ バキバキバキッ バサッ (rm -rfでたくさん削除する音)
さて、これでお掃除は完了です。.gitたくさん消えたので結構容量あいたはず! と思いきや意外と減ってない。たしかにゲーム開発で.gitが数百MB〜数GBのプロジェクトばっかり取り扱ってて感覚がマヒしてましたが、普通のgoのパッケージしか入ってないようなプロジェクトは大きくても数MBくらいなのでそんなに容量が空かないのでした。でも $GOPATH/src/github.com
の下がサッパリしただけでも気持ちよい。「なんか $GOPATH/src
の下が散らかってるよなぁ」という気持ちの問題は解決しました。
手持ちのプロジェクトをGo Modulesに移行しよう
ここからはおまけです(いちおうマイグレーションTrackなのでこれも書こうということで……)。
GO111MODULE=on
になるとgo.modファイルのないプロジェクトで go get
すると何が起きるのか、どうすればいいのかの話も書いておきます。
go.mod なしで go getするとエラーになる
(*'-')< project$ go get go: cannot find main module, but found .git/config in /path/to/project to create a module there, run: go mod init
その通り、エラーになりますが、どうすればいいか書いてあるので大丈夫です。go mod init
していきましょう。このときに注意点があって、起こることが2〜3パターンに分かれます。具体的にはどういうディレクトリで go mod init
したかによります。
$GOPATH/src/github.com/acidlemon/hoge
のような GOPATHの下の元々の場所$GOPATH/src/projects/hoge
のような GOPATHの下だけどちょっと移動させた場所- GOPATHの下じゃない、
$HOME/projects/hoge
のような場所
GOPATHの下で実行すると、 $GOPATH/src/
の下のパスがモジュール名として採用されるので、1の場合は module github.com/acidlemon/hoge
になります。これはまぁ普通ですが、2の場合は自動で module projects/hoge
というモジュール名になってしまいます。これはちょっと困ります。
GOPATHの外で実行すると、以下のようにエラーとなるので、go mod init
に追加の引数としてモジュールパス名を追加する必要があります。
(*'-')< hoge$ go mod init go: cannot determine module path for source directory /home/kawazoel/projects/hoge (outside GOPATH, module path must be specified) Example usage: 'go mod init example.com/m' to initialize a v0 or v1 module 'go mod init example.com/m/v2' to initialize a v2 module Run 'go help mod init' for more information.
ということで、go mod init
するときはとりあえず追加引数でモジュールパスを必ず入れておくようにするのがお勧めという感じです。それさえやっとけばあとは go get
してgo.modに依存関係を入れてgo.modファイルだけ git add
すればGo Modulesへの移行は完了! という感じです(昔からGOPATHにおいてあったソースコードと比較して、エイヤーでgo get
して全てが最新化されたときに互換性が壊れてないという前提です……)。
それでは、みなさまよいお年をお迎えください〜