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

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

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-10-25 07:55:02770ブラウズ

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

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

レシーバーのポインタと値の違いを調べるとき、値メソッドは次のようにできることに注意してください。ポインタ メソッドはポインタと値の両方で呼び出されますが、ポインタ メソッドはポインタのみに制限されます。この制限は、ポインター メソッドがレシーバーを変更できることに由来しており、値のコピーに対して呼び出された場合、変更は破棄されます。

ただし、値に対して呼び出されるポインター メソッドを示すコード例は混乱を引き起こします。コードは次のとおりです。

<code class="go">package main

import (
    "fmt"
    "reflect"
)

type age int

func (a age) String() string {
    return fmt.Sprintf("%d year(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("Type information:\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>

ドキュメントでは不可能であると記載されていますが、このコードはエラーなしでコンパイルおよび実行されます。では、この明らかな矛盾の原因は何でしょうか?

その答えは、アドレス指定可能な値の概念の中にあります。 Go 仕様では、「x (の型) のメソッド セットに m が含まれており、引数リストを m のパラメータ リストに割り当てることができる場合、メソッド呼び出し x.m() は有効です。」と定義されています。さらに、「x がアドレス可能で、&x のメソッド セットに m が含まれている場合、x.m() は (&x).m() の短縮形です。」

この場合、vAge はアドレス可能であり、有効なメモリ アドレスがあることを意味します。 。 vAge.Set() を呼び出すと、コンパイラーは、値のアドレスを使用してポインター レシーバー メソッド Set() を呼び出すこともできることを認識します。これは (&vAge).Set() と同等です。

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

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