ホームページ > バックエンド開発 > Golang > Go でスライスにポインタを追加すると、予期しない値が上書きされるのはなぜですか?

Go でスライスにポインタを追加すると、予期しない値が上書きされるのはなぜですか?

Barbara Streisand
リリース: 2024-12-15 09:24:10
オリジナル
497 人が閲覧しました

Why Does Appending Pointers to a Slice in Go Result in Unexpected Overwritten Values?

Golang の奇妙な「追加」動作: スライス内の値を上書きする

Golang では、スライスに追加する場合、その違いを理解することが不可欠ですポインター型と非ポインター型の間。

例を考えてみましょう。コード:

import "fmt"

type Foo struct {
    val int
}

func main() {
    var a = make([]*Foo, 1)
    a[0] = &Foo{0}

    var b = [3]Foo{Foo{1}, Foo{2}, Foo{3}}
    for _, e := range b {
        a = append(a, &e)
    }

    for _, e := range a {
        fmt.Printf("%v ", *e)
    }
}
ログイン後にコピー

期待される出力は {0} {1} {2} {3} ですが、代わりに {0} {3} {3} {3} が出力されます。これは、for ループが配列要素のコピーに対して動作するためです。

for ... 範囲を反復処理すると、一時的なループ変数が作成され、配列要素の値が割り当てられます。この場合、一時変数の型は Foo です。ただし、スライスに追加する場合、実際の配列要素のアドレスではなく、一時変数のアドレスが追加されます。

この一時変数は、ループ反復ごとに、配列の最後の要素の値で上書きされます。配列、つまり Foo{3} です。その結果、スライスには、配列の最後の要素を指す同じポインターへの参照が複数含まれています。

問題を解決するには、ループ変数の代わりに配列要素のアドレスを追加する必要があります。

for i := range b {
    a = append(a, &b[i])
}
ログイン後にコピー

この変更により、出力は期待どおりになります: {0} {1} {2} {3}。

この動作は、次の重要性を強調しています。 Go の型システムと、スライスを操作するときのポインタと非ポインタの区別を理解します。

以上がGo でスライスにポインタを追加すると、予期しない値が上書きされるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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