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