はじめに
最近、Goのブログで「Fixing For Loops in Go 1.22」という記事が公開されました。この記事では、Go 1.22でのforループの変数スコープに関する変更について詳しく説明されています。
以下、その内容を紹介します。
記事の内容
Goのコード書いていて、forループの変数スコープに関する問題に直面したことはありますか?
Go 1.22では、この問題に対する重要な変更が導入されます。
問題点
Goでの一般的なミスの一つは、ループ変数への参照をその反復の終了後も保持してしまうことです。
これにより、予期しない動作が生じることがあります。
例えば、以下のコードを考えてみましょう。
package main
import "fmt"
func main() {
done := make(chan bool)
values := []string{"a", "b", "c"}
for _, v := range values {
go func() {
fmt.Println(v)
done <- true
}()
}
// すべてのゴルーチンが終了するのを待つ
for _ = range values {
<-done
}
}
このコードでは、3つのゴルーチンがすべて同じ変数vを出力しているため、通常は「c」、「c」、「c」と出力されます。
しかし、期待される出力は「a」、「b」、「c」のいずれかの順序です。
修正
Go 1.22では、これらの変数のスコープをループ全体のスコープではなく、反復ごとのスコープに変更する予定です。これにより、上記のような問題が解消されます。
新しいセマンティクスは、go.modファイルでgo 1.22以降を宣言するモジュールに含まれるパッケージにのみ適用されます。これにより、後方互換性が確保されます。