ホームページ > バックエンド開発 > Golang > Go の直接スライス変換がポインタに同じメモリ アドレスを再利用するのはなぜですか?

Go の直接スライス変換がポインタに同じメモリ アドレスを再利用するのはなぜですか?

Mary-Kate Olsen
リリース: 2025-01-02 15:40:40
オリジナル
451 人が閲覧しました

Why Does Direct Slice Conversion in Go Reuse the Same Memory Address for Pointers?

Go スライスとメモリの再利用性

Go ポインタを含むプロジェクトで興味深い問題が発生しました。問題は、構造体オブジェクトのスライスをインターフェイスのスライスに変換するときに、最初のポインターのメモリ アドレスが出力で繰り返し使用されることでした。

この問題を解決するために、開発者は追加の関数を使用するように変換関数を変更しました。

これにより、元のソリューションがなぜ失敗したのかという疑問が生じます。これを理解するには、Go がポインターとスライスをどのように処理するかを詳しく調べる必要があります。

Go では、式 *coll は、基になる配列、その長さ、およびその容量に関する情報を含むスライス ヘッダーを返します。スライスの要素にアクセスする場合、式 (*coll)[idx] が使用され、インデックス idx の要素への参照が返されます。

元のソリューションでは、 item は範囲内のループ変数でした。 *コールループ。このループはスライス ヘッダーを反復処理し、スライスの各要素をループ変数項目に割り当てます。ただし、item はループ変数であるため、そのメモリ アドレスはループ全体を通じて同じままです。したがって、&item が出力スライスに追加されると、同じメモリ アドレスが複数回追加され、観察された動作が発生します。

修正されたソリューションでは、式 i := (*coll)[idx] を内で使用します。ループして、インデックス idx の要素をローカル変数 i に割り当てます。この変数にはループ変数項目とは異なるメモリ アドレスがあるため、&i が出力スライスに追加されると、各要素は異なるメモリ アドレスを持ちます。

ループ変数間のメモリ アドレスの違いを説明するには

package main

import "fmt"

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] には反復ごとに異なるメモリ アドレスがあります。

以上がGo の直接スライス変換がポインタに同じメモリ アドレスを再利用するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート