Étant donné l'exemple de code Go suivant :
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 }
Dans le code ci-dessus, vous pouvez appelez les deux méthodes de la struct tourGuide en utilisant soit une variable de type tourGuide (t1) soit un pointeur vers tourGuide (t2). Cependant, lors de la mise en œuvre des interfaces, les choses changent. Une variable de type greeter interface est assignable depuis un pointeur vers tourGuide, mais pas depuis une valeur tourGuide. Pourquoi est-ce le cas ?
Pour comprendre la raison, il est important de comprendre le concept de types de récepteurs et de sémantique des valeurs. Les méthodes dans Go peuvent avoir soit un récepteur de valeur, soit un récepteur de pointeur. Une méthode de réception de valeur est invoquée sur une copie de la valeur, tandis qu'une méthode de réception de pointeur est invoquée sur la valeur d'origine.
Lorsqu'une valeur est copiée, elle crée une nouvelle copie indépendante de la valeur d'origine. Les modifications apportées à la copie n'affectent pas la valeur originale. C'est ce qu'on appelle la sémantique des valeurs.
Dans l'exemple de tourGuide, la méthode hello a un récepteur de valeur et la méthode goodbye a un récepteur de pointeur. Lorsque vous appelez t1.hello(), une copie de t1 est créée et la méthode hello est invoquée sur la copie. Lorsque vous appelez t1.goodbye(), la méthode goodbye est invoquée sur la valeur t1 d'origine.
Les interfaces dans Go sont implémentées par la sémantique des valeurs. Cela signifie que lorsqu'une valeur est affectée à une interface, une copie de la valeur est créée. Dans le cas d'une méthode récepteur de pointeur, cela signifie que la copie de la valeur n'a pas d'adresse, et donc la méthode ne peut pas être invoquée dessus.
Par exemple, lorsque vous attribuez t1 à g1 (qui est une valeur d'interface) dans la ligne de code suivante :
// illegal: t1 is not assignable to g1 (why?) // var g1 greeter = t1
une copie de t1 est créée et les méthodes hello et goodbye sont implémentées sur la copie. Cependant, comme la copie n'a pas d'adresse, la méthode goodbye ne peut pas être invoquée sur elle.
En revanche, lorsque vous attribuez t2 à g2 dans la ligne de code suivante :
var g2 greeter = t2
une copie de t2 (qui est un pointeur vers tourGuide) est créée, et les méthodes bonjour et au revoir sont implémentées sur la copie du pointeur. Dans ce cas, la copie du pointeur a une adresse, donc la méthode goodbye peut être invoquée dessus.
En résumé, la raison pour laquelle une variable de type greeter interface est assignable d'un pointeur vers tourGuide mais pas d'une valeur tourGuide est dû au fait que les interfaces sont implémentées par la sémantique des valeurs. Lorsqu'une valeur est affectée à une interface, une copie de la valeur est créée, et si les méthodes de l'interface ont des récepteurs de pointeurs, elles ne peuvent pas être invoquées sur la copie car la copie n'a pas d'adresse.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!