Copie des valeurs d'interface dans Go
Les valeurs d'interface dans Go encapsulent un type dynamique et une valeur concrète sous-jacente. L'attribution d'une valeur d'interface à une autre copie la valeur sous-jacente, et non la valeur concrète d'origine elle-même. Cela peut entraîner un comportement inattendu lorsque vous travaillez avec des interfaces et des pointeurs vers des structures.
Considérez l'exemple suivant :
type User interface { Name() string SetName(name string) } type Admin struct { name string } func (a *Admin) Name() string { return a.name } func (a *Admin) SetName(name string) { a.name = name }
Dans cet exemple, l'administrateur implémente l'interface utilisateur. Nous créons une variable user1 de type User et l'initialisons avec un pointeur vers une structure Admin.
var user1 User user1 = &Admin{name: "user1"}
Maintenant, nous créons une nouvelle variable user2 et lui attribuons la valeur de user1.
var user2 User user2 = user1
Le problème ici est que user1 et user2 font référence à la même instance Admin. Changer le nom de l'utilisateur 2 modifie également le nom de l'utilisateur 1. En effet, la valeur de l'interface contient uniquement un pointeur vers la structure Admin sous-jacente.
Pour éviter cela, nous devons créer une nouvelle structure Admin pour l'utilisateur2. Nous pouvons utiliser la réflexion pour y parvenir :
var user2 User padmin := user1.(*Admin) // Obtain *Admin pointer admin2 := *padmin // Make a copy of the Admin struct user2 = &admin2 // Wrap its address in another User
Désormais, changer le nom de l'utilisateur2 n'affecte plus l'utilisateur1.
Cependant, cette solution nécessite que nous connaissions le type concret de la valeur de l'interface à l'avance. Une solution plus générale consiste à utiliser la réflexion pour créer une nouvelle instance du type dynamique de la valeur d'interface :
var user2 User if reflect.TypeOf(user1).Kind() == reflect.Ptr { // Pointer: user2 = reflect.New(reflect.ValueOf(user1).Elem().Type()).Interface().(User) } else { // Not pointer: user2 = reflect.New(reflect.TypeOf(user1)).Elem().Interface().(User) }
Cette solution fonctionne à la fois avec les valeurs d'interface pointeur et non-pointeur.
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!