2024年2月ごろリリース予定の Go 1.22 で、今まで多くのバグを生み出してきたであろうループ変数の共有がされなくなる。

Go 1.22 Release Notes

いままで

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
}

どう変わるのか

ループ変数をループごとに作成するようになる。 ただしどんなケースでも作成されるわけではなく、ループ変数が内部のクロージャなどから参照されたりしたときにだけ作成される。賢い!

注意

少なからず動作が変わるわけで、いままでループ変数が共有されていることを前提に動いていたコードが期待値通り動作しなくなるかもしれないが、レアケースだろうとしている。 さすがにそんなコードはないと信じたい。書こうとすればかけるけど、わざわざやる人いないでしょう…

パフォーマンスにごくわずかに影響がでるかもしれない