ホームページ  >  記事  >  バックエンド開発  >  値レシーバーを使用すると、Go 構造体で不正なスライス変更が発生するのはなぜですか?

値レシーバーを使用すると、Go 構造体で不正なスライス変更が発生するのはなぜですか?

Patricia Arquette
Patricia Arquetteオリジナル
2024-11-17 05:03:03976ブラウズ

Why Does Using a Value Receiver Lead to Incorrect Slice Modification in a Go Struct?

構造体のスライスから要素を削除する (解決済み)

提供されたコード スニペットでは、構造体を削除しようとすると問題が発生します。値レシーバーを使用して、構造体内のスライスから要素を取得します。これにより、元の構造体のスライスが誤って変更されます。

これを解決するには、スライスを変更するメソッドでポインタ レシーバを使用する必要があります。これは、Go 値レシーバーがレシーバー値のコピーを作成するためです。つまり、メソッド内でレシーバーに加えられた変更は元の構造体に反映されません。

修正されたコードは次のとおりです:

func (guest *Guest) removeFriend(id int) {
    for i, other := range guest.friends {
        if other == id {
            guest.friends = append(guest.friends[:i], guest.friends[i+1:]...)
            break
        }
    }
}

ポインター レシーバー (*Guest) を使用することにより、メソッドは元の Guest 構造体のフレンド スライスを変更し、要素が確実に削除されるようにします。

説明:

スライスが値によって渡されると、受信側メソッドはスライスのコピーを操作します。スライスに変更を加えた場合、変更はコピーにのみ反映され、元のスライスには反映されません。ただし、ポインタ レシーバを使用すると、レシーバが元の構造体へのポインタになるため、メソッドで元のスライスを変更できます。

使用例:

guest := &Guest{
    id:      1,
    name:    "Bob",
    surname: "Pats",
    friends: []int{1, 2, 3, 4, 5},
}

fmt.Println(guest)
guest.removeFriend(3)
fmt.Println(guest)

出力:

&{1 Bob Pats [1 2 3 4 5]}
&{1 Bob Pats [1 2 4 5]}

以上が値レシーバーを使用すると、Go 構造体で不正なスライス変更が発生するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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