Go: スライスからコピーしたメモリ アドレスの再利用
Go では、range 関数はスライスの要素を反復処理します。ただし、よくある落とし穴は、ループ変数のメモリ アドレスの再利用です。これにより、スライス要素を別のデータ構造にコピーしようとすると、予期しない結果が生じる可能性があります。
次のコード スニペットを考えてみましょう。
// Regions is the collection of the Region model type Regions []Region // Returns the model collection as a list of models func (coll *Regions) ToModelList() []Model { output := make([]Model, len(*coll)) for idx, item := range *coll { output[idx] = &item } return output }
このコードでは、ループ変数項目はポインタ参照です。 *coll スライス内の要素に追加します。 &item を出力スライスの要素に割り当てることにより、複数の要素が同じ基礎となる領域オブジェクトを指すことになります。これは、output と *coll が item の同じメモリ アドレスを共有しているために発生します。
この問題を解決するには、出力内の要素ごとに、Region オブジェクトの個別のコピーを作成する必要があります。これは、次のコード スニペットを使用して実現できます。
// Returns the model collection as a list of models func (coll *Regions) ToModelList() []Model { output := make([]Model, len(*coll)) for idx, _ := range *coll { i := (*coll)[idx] output[idx] = &i } return output }
この改訂されたコードでは、_ は *coll にわたる範囲のループ変数として使用されます。これにより、反復ごとに i の新しいコピーが確実に作成され、ループ反復間でのメモリ アドレスの再利用が防止されます。
このような種類の落とし穴を回避し、プログラムを正しく実行するには、Go のメモリ管理の微妙な違いを理解することが重要です。 .
以上がGo スライス: 「range」を使用してスライス要素をコピーすると、共有メモリ アドレスが発生する場合があるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。