次の Go コード例を考えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
|
上記のコードでは、次のことができます。 TourGuide (t1) 型の変数または TourGuide へのポインタを使用して、構造体 TourGuide の 2 つのメソッドを呼び出します。 (t2)。ただし、インターフェイスを実装すると状況が変わります。グリーター インターフェイス タイプの変数は、tourGuide へのポインターから割り当てることができますが、tourGuide 値からは割り当てることができません。なぜそうなるのですか?
その理由を理解するには、レシーバーのタイプと値のセマンティクスの概念を理解することが重要です。 Go のメソッドには、値レシーバーまたはポインタ レシーバーのいずれかを含めることができます。値レシーバー メソッドは値のコピーに対して呼び出されますが、ポインター レシーバー メソッドは元の値に対して呼び出されます。
値がコピーされると、元の値の新しい独立したコピーが作成されます。コピーに変更を加えても、元の値には影響しません。これは値セマンティクスとして知られています。
tourGuide の例では、hello メソッドには値レシーバーがあり、goodbye メソッドにはポインター レシーバーがあります。 t1.hello() を呼び出すと、t1 のコピーが作成され、そのコピー上で hello メソッドが呼び出されます。 t1.goodbye() を呼び出すと、元の t1 値に対して Goodbye メソッドが呼び出されます。
Go のインターフェースは値セマンティクスによって実装されます。これは、値がインターフェイスに割り当てられると、その値のコピーが作成されることを意味します。ポインタ レシーバ メソッドの場合、これは値のコピーにアドレスがないことを意味し、そのためメソッドを呼び出すことができません。
たとえば、t1 を g1 に代入すると (これははインターフェイス値です)。次のコード行では、
1 2 |
|
t1 のコピーが作成され、そのコピーに hello メソッドと Goodbye メソッドが実装されます。ただし、コピーにはアドレスがないため、コピーに対して Goodbye メソッドを呼び出すことはできません。
対照的に、次のコード行で t2 を g2 に代入すると、
1 |
|
t2 (tourGuide へのポインタ) のコピーが作成され、ポインタのコピーに hello メソッドと Goodbye メソッドが実装されます。この場合、ポインタのコピーにはアドレスがあるため、そのコピーに対して Goodbye メソッドを呼び出すことができます。
要約すると、グリーター インターフェイス型の変数が代入可能である理由TourGuide へのポインターからではなく、tourGuide 値からではないのは、インターフェイスが値セマンティクスによって実装されているためです。値がインターフェイスに割り当てられると、値のコピーが作成されます。インターフェイスのメソッドにポインター レシーバーがある場合、コピーにはアドレスがないため、コピー上でメソッドを呼び出すことはできません。
以上がGo の「greeter」インターフェイスには「tourGuide」値を割り当てることができないのに、「tourGuide」へのポインタを割り当てることはできるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。