Go ポインター: 値とポインター レシーバーを詳しく見る
Go では、ポインターはメモリを効果的に管理し、再利用可能なデータを作成する上で重要な役割を果たします。データ構造。初心者は、特に C/C などの言語とは異なるポインターの概念に取り組むことがよくあります。この記事は、Go ポインターのニュアンスを明確にし、よくある誤解に対処することを目的としています。
Go ツアー #52 から借用した以下のコード スニペットを考えてみましょう。
type Vertex struct { X, Y float64 } func (v *Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) } func main() { v := &Vertex{3, 4} fmt.Println(v.Abs()) }
ここでは、構造体を定義します。 Vertex、および頂点の絶対値を計算するメソッド Abs です。 Abs のレシーバ v は Vertex へのポインタです。これは、Abs が頂点へのポインタを操作し、元の頂点への変更を可能にすることを意味します。
次に、コードへのわずかな変更を考えてみましょう。
func (v Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) }
興味深いことに、この変更により次のことが起こります。同じ結果です。私たちの質問は次のとおりです: *Vertex を使用するか、Abs のレシーバーとして Vertex を使用するかに違いはありますか?
その答えは、Go の 2 つの基本的なルールにあります:
値とポインター レシーバーの変換: Go では、値レシーバーを持つメソッドからポインター レシーバーを持つメソッドを派生できます。したがって、 func (v Vertex) Abs() float64 は、追加の実装を自動的に生成します。
func (v Vertex) Abs() float64 { return math.Sqrt(v.X*v.X+v.Y*v.Y) } func (v *Vertex) Abs() float64 { return Vertex.Abs(*v) } // GENERATED METHOD
コンパイラは、生成されたメソッドをシームレスに検索し、v がポインタでないにもかかわらず v.Abs() が機能する理由を説明します。 .
自動アドレス取得: Go は変数のアドレスを自動的に取得できます。これは、ポインター レシーバーを使用せずに変更されたコードで v.Abs() を呼び出す場合、次と同等であることを意味します。
vp := &v vp.Abs()
したがって、明示的に & を使用するかどうかに関係なく、関数は依然として頂点へのポインターを受け取ります。 .
以上がGo ポインター: 値とポインター レシーバー - それは重要ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。