2024年2月ごろリリース予定の Go 1.22 で、今まで多くのバグを生み出してきたであろうループ変数の共有がされなくなる。
いままで
forループの変数は、ループごとに新しい変数を作るのではなく、同じアドレスに値を格納している。 これによって、ループ内でクロージャを呼んでいるようなコードは期待値通りに動作しない。
func main() {
strs := []string{"banana", "apple", "orange"}
var wg sync.WaitGroup
for _, v := range strs {
wg.Add(1)
go func() {
fmt.Println(v)
wg.Done()
}()
}
wg.Wait()
// exptected:
// banana
// apple
// orange
//
// actual:
// orange
// orange
// orange
}
どう変わるのか
ループ変数をループごとに作成するようになる。 ただしどんなケースでも作成されるわけではなく、ループ変数が内部のクロージャなどから参照されたりしたときにだけ作成される。賢い!
注意
少なからず動作が変わるわけで、いままでループ変数が共有されていることを前提に動いていたコードが期待値通り動作しなくなるかもしれないが、レアケースだろうとしている。 さすがにそんなコードはないと信じたい。書こうとすればかけるけど、わざわざやる人いないでしょう…
パフォーマンスにごくわずかに影響がでるかもしれない