LoginSignup
9
9

More than 3 years have passed since last update.

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

Last updated at Posted at 2017-04-10

追記

scopelintを廃止しました。

代わりにポリシーの違う2つのlintに分けました

注意

某Let's encryptの騒ぎで、まさにこの問題が根幹にあったみたいですね。
Scopelintがもうちょっとちゃんとしていれば…

現在、False positiveが取り除けていません
(ゆえに主要なlinter suiteでdefault offになっています)

contribution、お待ちしています。

kyoh86/scopelint

動機

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

example/readme.go
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ライフを!

9
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9