ホームページ >バックエンド開発 >Golang >Go のスライス範囲ループをマップで使用すると予期しない動作が発生するのはなぜですか?

Go のスライス範囲ループをマップで使用すると予期しない動作が発生するのはなぜですか?

Linda Hamilton
Linda Hamiltonオリジナル
2024-12-09 01:54:12390ブラウズ

Why Does Go's Slice Range Loop Create Unexpected Behavior When Used with Maps?

Go のスライス範囲の動作のデコード

Go では、スライスは動的な配列のような機能を提供する多用途のデータ構造です。スライスを反復処理する場合、範囲構文を使用すると、その要素にアクセスする便利な方法が提供されます。ただし、特定のシナリオでは予期しない動作が発生する可能性があります。

スチューデント構造体のスライスを作成し、これらの構造体への参照をマップに設定する次のコードを考えてみましょう。

type student struct {
    Name string
    Age  int
}

func main() {
    m := make(map[string]*student)
    s := []student{
        {Name: "Allen", Age: 24},
        {Name: "Tom", Age: 23},
    }

    for _, stu := range s {
        m[stu.Name] = &stu
    }

    fmt.Println(m) // map[Allen:0xc42006a0c0 Tom:0xc42006a0c0]
}

期待される動作は次のとおりです。マップには、スライス内の個々の Student 構造体への参照が含まれている必要があります。ただし、結果は、マップ内の両方のキーが同じアドレスを指していることを示しています。

この動作は、範囲ループ内の stu 変数が参照ではなくスライス要素のコピーであることを理解することで説明できます。 stu.Name は名前フィールドのコピーを取得し、&stu はそのコピーのアドレスを取得します。その結果、すべてのマップ値のアドレスが同じになります。

この問題を修正するには、コードは、代わりに実際のスライス要素:

for i := range s {
    m[s[i].Name] = &s[i]
}

スライス要素に直接アクセスすることで、その一意のメモリ位置への参照を取得し、予期しない動作を解決し、マップに各スライス要素への参照が含まれていることを確認します。学生構造体。

以上がGo のスライス範囲ループをマップで使用すると予期しない動作が発生するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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