ホームページ >バックエンド開発 >Golang >## Go で値のポインター メソッドを呼び出すことができるのはなぜですか?

## Go で値のポインター メソッドを呼び出すことができるのはなぜですか?

Barbara Streisand
Barbara Streisandオリジナル
2024-10-25 13:21:02381ブラウズ

## Why Can I Call a Pointer Method on a Value in Go?

Go レシーバー メソッド呼び出し構文の混乱

Effective Go の「ポインターと値」セクションでは、「値メソッドはポインターと値で呼び出すことができる」と記載されています。ただし、ポインタ メソッドはポインタに対してのみ呼び出すことができます。」これは、ポインタ メソッドがレシーバを変更する可能性があり、値のコピーに対してポインタ メソッドを呼び出すと、これらの変更が破棄されてしまうためです。

しかし、一部の開発者は、それらを実行できる状況に遭遇しました。値に対してポインター メソッドを呼び出しますが、これは文書化された構文規則に矛盾しているように見えます。この混乱を明確にするために、この動作をさらに詳しく調べます。

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

<code class="go">package main

import (
  "fmt"
  "reflect"
)

type age int

func (a age) String() string {
  return fmt.Sprintf("%d yeasr(s) old", int(a))
}

func (a *age) Set(newAge int) {
  if newAge >= 0 {
    *a = age(newAge)
  }
}

func main() {
  var vAge age = 5
  pAge := new(age)

  fmt.Printf("TypeOf =>\n\tvAge: %v\n\tpAge: %v\n", reflect.TypeOf(vAge),
    reflect.TypeOf(pAge))

  fmt.Printf("vAge.String(): %v\n", vAge.String())
  fmt.Printf("vAge.Set(10)\n")
  vAge.Set(10)
  fmt.Printf("vAge.String(): %v\n", vAge.String())

  fmt.Printf("pAge.String(): %v\n", pAge.String())
  fmt.Printf("pAge.Set(10)\n")
  pAge.Set(10)
  fmt.Printf("pAge.String(): %v\n", pAge.String())
}</code>

この例では、2 つのメソッドを使用して age タイプを定義します。 String( ) (値メソッド) と Set() (ポインター メソッド)。このコードは、2 つの変数を作成します。vAge (age 型の値)、および pAge (年齢値へのポインター) です。

ドキュメントでは、vAge.Set() が有効な構文ではないことが示されているにもかかわらず、コードは次の構文を使用せずにコンパイルされます。エラー。これは、vAge がアドレス可能である、つまり参照できるメモリ アドレスがあるためです。言語仕様に従って、アドレス指定可能な変数 x に対するメソッド呼び出し x.m() は、x のメソッド セットに m が含まれている場合に有効です。

この場合、vAge はアドレス指定可能であり、*age のメソッド セットには Set が含まれているため、 () の呼び出し vAge.Set() は (&vAge).Set() の短縮表記です。基本的に、&演算子は、vAge へのポインターを取得するために暗黙的に使用されています。

したがって、このコードは、アドレス指定可能な値に対する値メソッドの呼び出しは、その値へのポインターに対するメソッドの呼び出しと同等であるため、実際にポインターに対して値メソッドを呼び出すことができることを示しています。価値。ポインタ メソッド Set() は依然としてポインタに対してのみ呼び出すことができますが、値がアドレス指定可能な場合は、暗黙的な逆参照により構文 vAge.Set() が有効になります。

以上が## Go で値のポインター メソッドを呼び出すことができるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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