Go ポインタ: ポインタのセマンティクスを解明する
ポインラーは、参照によるメモリ アドレスと値の操作を可能にする Go プログラミングの基本概念です。ポインタは他のプログラミング言語と類似点を共有していますが、Go のポインタ セマンティクスは独特であり、初心者にとって混乱を引き起こす可能性があります。
次のコードを考えてみましょう。
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 構造体とfunc (v *Vertex) Abs() メソッド。頂点の座標の絶対値を計算します。メソッド レシーバーをポインター *Vertex として宣言することで、メソッドが Vertex 値へのポインターで動作することを示します。
コードを次のように変更すると、
func (v Vertex) Abs() float64 { [...] v := &Vertex{3, 4} }
ここでレシーバがポインタではなく値 (Vertex) になった場合、同じ結果が得られます。その理由は 2 つあります:
メソッド導出: Go では、値レシーバーを持つメソッドからポインター レシーバーを持つメソッドを導出できます。これは、メソッド func (v Vertex) Abs() が追加のメソッド実装を自動的に生成することを意味します。
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.Abs() を呼び出すと (v はポインターではない)、コンパイラーは自動的に
自動アドレス取得: Go には、変数のアドレスを自動的に取得する機能があります。以下のコード:
func (v *Vertex) Abs() float64 { return math.Sqrt(v.X*v.X+v.Y*v.Y) } func main() { v := Vertex{3, 4} v.Abs() }
式 v.Abs() はコードと同等です:
vp := &v vp.Abs()
このシナリオでは、コンパイラーは自動的に v 変数のアドレスを取得します。そしてそれをポインタ レシーバ メソッド func (v *Vertex) Abs() に渡します。
したがって、コード変更の場合は、前述したように、Abs() メソッドに値を渡すかポインターを渡すかに関係なく、Go のポインター セマンティクスにより正しい動作が保証されます。ただし、Go で構造体などの参照型を操作する場合は、ポインターを使用することが一般的に良い方法であると考えられています。
以上がGo ポインター: メソッドに値またはポインターを渡すことができるように見えるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。