Go のスライス範囲現象を理解する
Go では、スライス範囲の動作がわかりにくい場合があります。 range 句を使用してスライスを反復処理する場合、反復変数が各要素のアドレスを保持していると信じてしまいがちです。ただし、常にそうとは限りません。そのようなシナリオの 1 つは、構造体とマップを操作する場合です。
次のコードを考えてみましょう:
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 } }
このコードは、構造体のスライスを反復処理し、キーと値のペアをマップに追加します。各構造体を取得し、その構造体のアドレスを値として格納します。ただし、結果のマップは、すべての値が同じアドレスを指していることを示しています。
この現象を説明するには、スライス範囲の基礎となる実装を確認する必要があります。 range 句を使用してスライスが反復されると、反復変数はスライスから要素のコピーを受け取ります。したがって、反復変数は、構造体のアドレスではなく、構造体のコピーを保持します。
この問題を修正して構造体のアドレスをマップに保存するには、スライス要素のアドレスを取得するようにコードを変更する必要があります。 :
for i := range s { m[s[i].Name] = &s[i] }
この変更により、反復変数が構造体のアドレスを保持し、マップがスライス内の各構造体のアドレスを正しく格納するようになります。
以上がGo でスライス範囲を反復すると、アドレスではなくコピーが返される場合があるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。