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言語」で僕が書いた章の中で紹介させてもらっていたので、開発にコントリビュートできたのは嬉しかったです。