ホームページ >バックエンド開発 >Golang >ポインター レシーバーを使用した Go メソッドがポインター以外の引数を変更するのはなぜですか?

ポインター レシーバーを使用した Go メソッドがポインター以外の引数を変更するのはなぜですか?

Barbara Streisand
Barbara Streisandオリジナル
2024-12-05 11:35:11484ブラウズ

Why Does a Go Method with a Pointer Receiver Modify a Non-Pointer Argument?

なぜポインタ レシーバを使用したメソッドは、非ポインタを受信して​​も値が変更されるのですか?

Go では、ポインタ レシーバを使用したメソッドは、操作する変数の元の値を保持することが知られています。の上。ただし、メソッドがポインター引数を予期しているのに、ポインター以外の値が渡された場合、明らかな矛盾があるようです。

Go ツアーの演習 51 の以下のスニペットを考えてみましょう。

func (v *Vertex) Scale(f float64) {
    v.X *= f
    v.Y *= f
}

func main() {
    v := &Vertex{3, 4}
    v.Scale(2)
    fmt.Println(v) // Output: &{6 8}
}

説明によると、Scale メソッドは Vertex ではなく Vertex (*Vertex) へのポインタを受け取るため、v を変更すべきではありません。

ただし、main で v := &Vertex{3, 4} 行を v := Vertex{3, 4} に変更すると、出力は &{6 8} から {6 8 に変わります。 } (& が欠落していることに注意してください)。これは、v が非ポインター値として渡されたにもかかわらず、変更されたことを示します。

説明

鍵は、Go の厳密に型指定された性質とコンパイラーの最適化にあります。 Scale メソッドはポインター レシーバーを想定していますが、Go は暗黙的にポインターに変換するため、ポインター以外の値も受け入れることができます。

具体的には、コンパイラーは次のコードを書き換えます。

v := Vertex{3, 4}
v.Scale(2)

to:

(&v).Scale(2)

これは、メソッドが実際に v へのポインターを使用して呼び出されることを意味します。元の値を変更します。

次の Go 固有のルールは、この動作を説明します。

x (の型) のメソッド セットに m が含まれており、引数リストを m のパラメータ リストに割り当てることができます。 x がアドレス指定可能で、&x のメソッド セットに m が含まれている場合、x.m() は (&x).m() の短縮形です。

要約すると、コンパイラーが自動的に変換するため、ポインター レシーバーを持つメソッドでも非ポインター変数を変更できます。メソッドの型の安全性を維持するためのポインターへのそれら。

以上がポインター レシーバーを使用した Go メソッドがポインター以外の引数を変更するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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