Go ポインター: メソッドに値またはポインターを渡すことができるように見えるのはなぜですか?

Linda Hamilton
リリース: 2024-11-10 13:57:02
オリジナル
732 人が閲覧しました

 Go Pointers: Why Does It Seem Like I Can Pass Either a Value or a Pointer to My Method?

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 サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート