golangのループ変数の使い方をチェックするlinter作ってみた

動機

golangでforループを回すと、中でうっかりクロージャやリファレンスを取れません。

package example

import "fmt"

func readme() {
	values := []string{"a", "b", "c"}
	var funcs []func()
	for _, val := range values {
		funcs = append(funcs, func() {
			fmt.Println(val)
		})
	}
	for _, f := range funcs {
		f()
	}
	/*output:
	  c
	  c
	  c
	*/
	var copies []*string
	for _, val := range values {
		copies = append(copies, &val)
	}
	/*(in copies)
	  &"c"
	  &"c"
	  &"c"
	*/
}

意外と気づきにくいバグの元になってプログラマは容易に死にます。 一応一部のケースは go vet でも検出できますが、万能ではありません。(なぜか go func(){ }() だけは気をつけてくれる)

ならチェックしようぜ!ということでlinter作りました。

scopelint

使い方

golint とほぼ同じです。 go get -u github.com/kyoh86/scopelint でインストールして、雑にパッケージとかディレクトリとかファイルを渡してください。

scopelint github.com/kyoh86/scopelint/example
scopelint ./...

幾つかオプションも用意しました。

  • --set-exit-status : golintに同じ。エラーがあれば終了コードを 1 に設定する。毎回指定するのアホらしいので、デフォルト true
  • --vendor : vendor ディレクトリの下は見ない。これもデフォルト true
  • --test : *_test.go なファイルは見ない。これもデフォry

終わりに

あちこち golint のソースをコピペして作っています。ライセンス書かなきゃ… とまれ、良きgopherライフを!