No.63: ゴルーチンとループ変数の扱いに注意しない
ゴルーチンがクロージャで、その本体の外で宣言された反復変数にアクセスするのなら、それは問題だ。
ループ変数を、ループの中のクロージャのゴルーチンで参照した場合。
クロージャのゴルーチンが実行される時、ゴルーチンが作成された時の値を捕捉しないことを知っていなければならない。
ゴルーチンが作成された時の値を参照するのではなく、すべてのゴルーチンは同じ変数を参照する。
これを防ぐ方法1
反復ごとのローカル変数を作成する
このコードでは123(順不同)が表示される
for _, i := range s {
val := i // 反復ごとのローカル変数を作成
go func() {
fmt.Print(val)
}()
}
これを防ぐ方法2
クロージャに頼らない
for _, i := range s {
go func(val int) { // 引数としてうけとる
fmt.Print(val)
}(i) // この関数を呼び出してiの値を渡す
}