Go でのメモリ アドレスの再利用: Range 関数を理解する
Go でスライスを操作する場合、range 関数がどのように相互作用するかを理解することが重要ですあなたのデータと一緒に。プロジェクトで最近発生した問題により、スライス内のポインターの動作に関する疑問が生じました。具体的には、なぜ特定のメソッドが間違ったメモリ アドレスを返したのか、また、代替ソリューションはどのようにしてこの問題を解決できたのでしょうか?
元のメソッド ToModelList は、Region オブジェクト (Regions) のスライスをリストに変換することを目的としていました。モデルインターフェイスの。ただし、リージョンへの最初のポインターが出力内で繰り返し複製されました。これを修正するために、メソッドの修正バージョンが導入されました。
しかし、このわずかな修正はどのような違いをもたらしたのでしょうか?鍵となるのはレンジ関数を理解することです。 ToModelList の最初のバージョンでは、 item がループ変数でした。値が変化しても、アドレスは一定のままです。その結果、出力スライス内の複数の要素に同じアドレスが割り当てられました。
改訂版では、ループ構文が変更されました: for idx, := range *coll。今回は、未使用のループ変数のプレースホルダーとして を使用し、インデックス idx を使用して実際の項目にアクセスできるようにしました。 *coll を介してアイテムに間接的にアクセスすることで、繰り返しごとに新しいアドレスが使用されるようになり、メモリ再利用の問題が解決されました。
これをさらに説明するために、次のコードを考えてみましょう:
func main() { coll := []int{5, 10, 15} for i, v := range coll { fmt.Printf("Always the same: %v\n", &v) fmt.Println("Increments by 4 bytes each iteration: %v\n", &coll[i]) } }
この例では、最初のループ変数 v は常に同じメモリ アドレスを参照しますが、2 番目のループ変数 &coll[i] は反復ごとに 4 バイトずつ増加します。これは、ループ変数の使用と要素に直接アクセスすることの違いを示しています。
Go でスライスを操作するには、range 関数の内部動作を理解することが不可欠です。提供されている例では、潜在的な落とし穴と、ループ構文が結果にどのような影響を与える可能性があるかを強調しています。
以上がGo の「range」関数がメモリ アドレスを再利用するのはなぜですか?これを回避するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。