ghqを使っていても(使っていなくても)goimportsを爆速にする
「ghqを使ったローカルリポジトリの統一的・効率的な管理について」というエントリで書かれているように、 ghq.root と $GOPATH/src を一緒にする運用で長年やってきて、goimports が遅いことに少し困っていたのだが、以下でめちゃくちゃ快適になった。
- .goimportsignore を使う
goimports-update-ignoreで自動生成をする
- 最新の
dragon-importsを使う
どれくらい快適になったかというと、エディタの保存時に goimports を気兼ねなく実行させられるようになったくらい。以下解説。
.goimportsignoreを使う
最近の goimports には $GOPATH/src/.goimportsignore という除外リスト機能がある。ここにインポート対象外にしたいディレクトリを $GOPATH/src 以下の相対パスで記述すると、 goimports はそこを無視する。 ghq を使って、 $GOPATH/src 以下にGo言語以外のリポジトリもガンガンcloneしまくっている自分としては非常に助かる。
goimports-update-ignore で自動生成をする
もちろん、この .goimportsignore をイチイチ記述するのは現実的ではないので、 goimports-update-ignore というツールで自動生成する。go get でインストールできる。
% go get github.com/pwaller/goimports-update-ignore
goimports-update-ignore はGo以外の言語のディレクトリを抽出して、 .goimportsignore に追記してくれるコマンド。以下のように実行する。
% goimports-update-ignore -max-depth 5
-max-depth オプションはデフォルトで3だが、ちょっと足りないので5にしている。実行時間はちょっとかかるのでちょっと待とう。僕の手元だと40秒程度。
goimports-update-ignore の地味に良い点は、自動生成部分以外に自分が除外したいディレクトリの記述をしておけるところです。例えば、僕はGoのソースコードを読むために github.com/golang/go をcloneしていますが、これは当然 goimports の対象になって欲しくない。ただし、これは当たり前ですがGo言語のプロジェクトなので、 goimports-update-ignore には除外対象とはみなされません。
ですので、僕の .goimportsignore の冒頭は以下のようになっています。
github.com/golang
# Generated by goimports-update-ignore 2018-08-28 15:54:41.607268 +0000 UTC
anonscm.debian.org
cloud.google.com/go/bigtable/testdata
cloud.google.com/go/datastore/testdata
(snip)
先頭の github.com/golang は手で書き加えたものですが、この時 # Generated... 以前の部分は、 goimports-update-ignore を再度実行しても書き換わることがないのです。ですので、ここに自分が個別に除外したいディレクトリを書いておくことができます。
僕は goimports-update-ignore は気が向いたときに再実行して、 .goimportsignore を再生成するようにしています。これで .goimportsignore を活用できるようになり、 goimports が現実的な速度で動くようになりました。
最新の dragon-imports を使う
「現実的な速度」で動くようになったと前項で書きましたが、それでもGoライブラリの数が増えると挙動がもっさりしてきます。そこで、更に goimports を速くする方法として、 dragon-imports という裏技的なツールがあります。
これは、今ローカルに入っているライブラリ情報を抽出して、 goimports コマンド自体を作り直してしまうというなかなか豪快なツールです。詳しくは作者の「goimportsを高速化するdragon-importsコマンドをつくった」というエントリを参照ください。
こちらも go get でインストールして、 dragon-imports コマンドをおもむろに実行するだけです。
% go get github.com/monochromegane/dragon-imports/cmd/dragon-imports
% dragon-imports
これで、 goimports コマンドが作りなおされ、実行速度が爆速になりました。こちらも気が向いたタイミングで再実行して作り直すと良いでしょう。
実は、 dragon-imports は近年のGoのフィーチャーに追随できていないところがありました。そこで、最近僕が盆栽活動のように幾つかpull requestを送り、取り込んでもらいました。これで、 .goimportsignore を見るようになったり、 vendor/ を無視するようになり精度が向上しました。
結果、以前よりも安定しつつも更に爆速になり、出たばかりのGo1.11でもお使いいただけるようになっています。もし古いものをお使いの場合は最新をお試しください。
ということで、これでかなりGoの開発が快適になりました。
ちなみに、 dragon-imports は「みんなのGo言語」で僕が書いた章の中で紹介させてもらっていたので、開発にコントリビュートできたのは嬉しかったです。