ホームページ >バックエンド開発 >Golang >Go スライスからコピーするとメモリ アドレスが再利用されるのはなぜですか?それを修正するにはどうすればよいですか?

Go スライスからコピーするとメモリ アドレスが再利用されるのはなぜですか?それを修正するにはどうすればよいですか?

Barbara Streisand
Barbara Streisandオリジナル
2024-12-25 21:34:11394ブラウズ

Why Does Copying from a Go Slice Result in Memory Address Reuse, and How Can It Be Fixed?

Golang スライスからコピーするときのメモリ アドレスの再利用

Go プログラミングでよくある誤解は、スライスからのメモリ アドレスのコピーに関するものです。次の状況を考えてみましょう:

Model インターフェイスと、それを実装する Regional struct があります。インターフェイスは、Region 構造体のポインタに実装されます。また、Region オブジェクトのスライスである Regionals コレクションもあります。 Regionals オブジェクトを []Model に変換するメソッドがあります:

// 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
}

このコードを実行すると、出力スライス内のモデルごとに個別のアドレスが取得されることが期待されます。ただし、リージョンへの最初のポインターが複数回出力されることになります。

この問題を解決するには、元のメソッドのループ変数項目を検討してください。これはループのすべての反復で同じであるため、結果のスライスには同じ基になるデータへの参照が含まれます。

一方、実用的なソリューションでは、 i := (*coll)[idx] を使用して反復ごとに新しい変数を作成します。これにより、出力スライス内の各モデルが一意のメモリ アドレスを持つことが保証されます。

よりよく理解するには、次のコード スニペットを検討してください。

func main() {
    coll := []int{5, 10, 15}

    for i, v := range coll {
        fmt.Printf("This one is always the same; %v\n", &v)
        fmt.Println("This one is 4 bytes larger each iteration; %v\n", &coll[i])
    }
}

このコードは、v のメモリ アドレスがcoll[i] のメモリ アドレスはループ全体で同じままですが、反復ごとに増加します。この動作は、v がループ変数であり、定数のままであるのに対し、coll[i] は反復ごとに新しい変数であるためです。

以上がGo スライスからコピーするとメモリ アドレスが再利用されるのはなぜですか?それを修正するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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