ホームページ >バックエンド開発 >Golang >ポインターの代わりにオブジェクトを使用して、ポインター レシーバーで Go メソッドを呼び出すことができるのはなぜですか?

ポインターの代わりにオブジェクトを使用して、ポインター レシーバーで Go メソッドを呼び出すことができるのはなぜですか?

DDD
DDDオリジナル
2024-12-28 11:41:21722ブラウズ

Why Can I Call a Go Method with a Pointer Receiver Using an Object Instead of a Pointer?

オブジェクトを使用したポインターを対象としたメソッドの呼び出し

Go では、それへのポインタの代わりにオブジェクトを使用します。これは珍しいように思えるかもしれませんが、Go 仕様に従って許可されています。

次のコードを考えてみましょう:

package main

import "math"

type Vertex struct {
    X, Y float64
}

func (v Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

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

func main() {
    v := Vertex{3, 4}
    v.Scale(10) // v is not a pointer to a Vertex object
    fmt.Println(v.Abs())
}

この例では、v は Vertex 型のオブジェクトで、Scale はVertex へのポインターを対象としたメソッド。ただし、v へのポインターを渡す代わりに、v.Scale(10) を直接呼び出します。

これがエラーではないのはなぜですか?答えは、Go 仕様で定義されているメソッド呼び出しのルールにあります。

If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m().

このルールは、呼び出される値がアドレス指定可能 (つまり、ローカル変数またはポインタである) の場合、呼び出しを行うことを示しています。そのメソッドは、そのアドレスでメソッドを呼び出すことと同じです。この場合、v はローカル変数であるため、v.Scale(10) は、代わりに (&v).Scale(10) を記述したかのように解釈されます。

この利便性により、よりクリーンで簡潔な記述が可能になります。メソッドを呼び出す前にオブジェクトへのポインタを明示的に作成する必要がなく、コードを作成できます。ただし、これはポインタ レシーバを備えたメソッドに対してのみ機能することに注意することが重要です。値レシーバーを持つメソッドの場合、オブジェクトへのポインターを渡すことは許可されません。

以上がポインターの代わりにオブジェクトを使用して、ポインター レシーバーで Go メソッドを呼び出すことができるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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