ホームページ >バックエンド開発 >Golang >Go の「greeter」インターフェイスには「tourGuide」値を割り当てることができないのに、「tourGuide」へのポインタを割り当てることはできるのはなぜですか?

Go の「greeter」インターフェイスには「tourGuide」値を割り当てることができないのに、「tourGuide」へのポインタを割り当てることはできるのはなぜですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-11-20 01:38:03221ブラウズ

Why can't a Go `greeter` interface be assigned a `tourGuide` value, but can be assigned a pointer to a `tourGuide`?

インターフェイスを満たす Go Struct メソッドの種類

次の Go コード例を考えます。

package main

import "fmt"

type greeter interface {
    hello()
    goodbye()
}

type tourGuide struct {
    name string
}

func (t tourGuide) hello() {
    fmt.Println("Hello", t.name)
}

func (t *tourGuide) goodbye() {
    fmt.Println("Goodbye", t.name)
}

func main() {
    var t1 tourGuide = tourGuide{"James"}
    t1.hello()   // Hello James
    t1.goodbye() // Goodbye James (same as (&t1).goodbye())

    var t2 *tourGuide = &tourGuide{"Smith"}
    t2.hello()   // Hello Smith
    t2.goodbye() // Goodbye Smith (same as (*t2).hello())

    // illegal: t1 is not assignable to g1 (why?)
    // var g1 greeter = t1

    var g2 greeter = t2
    g2.hello()   // Hello Smith
    g2.goodbye() // Goodbye Smith
}

上記のコードでは、次のことができます。 TourGuide (t1) 型の変数または TourGuide へのポインタを使用して、構造体 TourGuide の 2 つのメソッドを呼び出します。 (t2)。ただし、インターフェイスを実装すると状況が変わります。グリーター インターフェイス タイプの変数は、tourGuide へのポインターから割り当てることができますが、tourGuide 値からは割り当てることができません。なぜそうなるのですか?

レシーバーのタイプと値のセマンティクス

その理由を理解するには、レシーバーのタイプと値のセマンティクスの概念を理解することが重要です。 Go のメソッドには、値レシーバーまたはポインタ レシーバーのいずれかを含めることができます。値レシーバー メソッドは値のコピーに対して呼び出されますが、ポインター レシーバー メソッドは元の値に対して呼び出されます。

値がコピーされると、元の値の新しい独立したコピーが作成されます。コピーに変更を加えても、元の値には影響しません。これは値セマンティクスとして知られています。

tourGuide の例では、hello メソッドには値レシーバーがあり、goodbye メソッドにはポインター レシーバーがあります。 t1.hello() を呼び出すと、t1 のコピーが作成され、そのコピー上で hello メソッドが呼び出されます。 t1.goodbye() を呼び出すと、元の t1 値に対して Goodbye メソッドが呼び出されます。

インターフェースと値セマンティクス

Go のインターフェースは値セマンティクスによって実装されます。これは、値がインターフェイスに割り当てられると、その値のコピーが作成されることを意味します。ポインタ レシーバ メソッドの場合、これは値のコピーにアドレスがないことを意味し、そのためメソッドを呼び出すことができません。

たとえば、t1 を g1 に代入すると (これははインターフェイス値です)。次のコード行では、

// illegal: t1 is not assignable to g1 (why?)
// var g1 greeter = t1

t1 のコピーが作成され、そのコピーに hello メソッドと Goodbye メソッドが実装されます。ただし、コピーにはアドレスがないため、コピーに対して Goodbye メソッドを呼び出すことはできません。

対照的に、次のコード行で t2 を g2 に代入すると、

var g2 greeter = t2

t2 (tourGuide へのポインタ) のコピーが作成され、ポインタのコピーに hello メソッドと Goodbye メソッドが実装されます。この場合、ポインタのコピーにはアドレスがあるため、そのコピーに対して Goodbye メソッドを呼び出すことができます。

結論

要約すると、グリーター インターフェイス型の変数が代入可能である理由TourGuide へのポインターからではなく、tourGuide 値からではないのは、インターフェイスが値セマンティクスによって実装されているためです。値がインターフェイスに割り当てられると、値のコピーが作成されます。インターフェイスのメソッドにポインター レシーバーがある場合、コピーにはアドレスがないため、コピー上でメソッドを呼び出すことはできません。

以上がGo の「greeter」インターフェイスには「tourGuide」値を割り当てることができないのに、「tourGuide」へのポインタを割り当てることはできるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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