1 ポイント 投稿者 GN⁺ 2023-09-20 | 1件のコメント | WhatsAppで共有
  • まもなく登場する Go 1.22 リリースでは、多くの企業で本番上の問題を引き起こしてきた for ループ範囲に関する一般的な誤りを修正する予定です。
  • この問題は、反復の終了後もループ変数への参照が保持され、その結果として意図しない新しい値を持つようになると発生します。
  • この問題は、同期・非同期の両方の Go コードで一般的であり、変数への参照が反復をまたいで存続するかどうかを分析する複雑さのため、特定と修正が困難でした。
  • こうしたミスを特定する既存ツールは、しばしば偽陰性または偽陽性を生み、不要なコード変更や見落とされた問題を招いていました。
  • Go 1.22 で提案されている修正では、for ループが反復スコープではなくループスコープを持つように変更され、この種のミスと不正確なツールの必要性を取り除きます。
  • 下位互換性を維持するため、新しいセマンティクスは go.mod ファイルで Go 1.22 以降を宣言しているモジュールに含まれるパッケージにのみ適用されます。
  • 開発者は、特定のパッケージでセマンティクスがいつ変更されるかを制御でき、既存コードはこれまでどおり動作し続けます。
  • Go 1.21 には、環境で GOEXPERIMENT=loopvar を設定することで有効化できる、このスコープ変更のプレビューが含まれています。
  • この変更は Google で広範にテストされており、本番コードで報告された問題はありません。
  • ただし、ループ変数の問題により、本来テストすべき内容をテストできていなかった一部のテストは修正が必要でした。
  • Go 1.21 の loopclosure アナライザーは、この種の問題を特定して報告する能力が改善されており、開発者が Go 1.22 での変更に備えるのに役立ちます。
  • この変更の詳細は、設計ドキュメントと FAQ で確認できます。

1件のコメント

 
GN⁺ 2023-09-20
Hacker Newsのコメント
  • 'Go 1.22' における 'for loops' 問題の議論で、クロージャ内でのループ変数の誤用に焦点が当てられている
  • クロージャ内でのループ変数の誤用という問題は新しいものではなく、1992年の Lisp 言語にまでさかのぼる
  • C# 言語チームもこの問題に直面し、C# 5.0 でこれを解決するために重大な変更を実施した
  • Go 1.21 は Go 1.22 以降を宣言するコードをコンパイルしないため、新しい意味論に依存するコードが古い意味論でコンパイルされないことが保証される
  • この変更が現在の挙動に依存しているプログラムを壊してしまうのではないかという懸念がある
  • パッケージが 1.22 に固定され、ユーザーが 1.18 でコンパイルする場合に実際にはどのように動作するのか疑問を呈するユーザーもいる
  • この変更がメモリ割り当てやループ性能に与える影響についての質問もある
  • Python のような他の言語で同様の問題を経験したことを共有するユーザーもいる
  • Go 1.22 の変更は言語構文の問題を解決する方法のように見えるが、あるファイルで宣言されたバージョンを知らなければ別のファイルの挙動を理解できないため、一部のユーザーには直感的でないと感じられている