ホームページ >バックエンド開発 >Golang >Go スライス: 「range」を使用してスライス要素をコピーすると、共有メモリ アドレスが発生する場合があるのはなぜですか?

Go スライス: 「range」を使用してスライス要素をコピーすると、共有メモリ アドレスが発生する場合があるのはなぜですか?

Linda Hamilton
Linda Hamiltonオリジナル
2024-12-19 02:12:09488ブラウズ

Go Slices: Why Does Copying Slice Elements Using `range` Sometimes Lead to Shared Memory Addresses?

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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。