Comment copier en profondeur une valeur d'interface dans Go
Lorsque vous travaillez avec des interfaces dans Go, il est essentiel de réaliser que les interfaces contiennent une référence à leur valeur sous-jacente. La modification de la copie d'une valeur d'interface peut également affecter par inadvertance la valeur d'origine. Ce problème survient généralement lors de la création de valeurs d'interface à l'aide de pointeurs vers des types sous-jacents.
Comprendre le problème
Considérez l'interface utilisateur suivante :
type User interface { Name() string SetName(name string) }
Et une implémentation avec une structure Admin :
type Admin struct { name string } func (a *Admin) Name() string { return a.name } func (a *Admin) SetName(name string) { a.name = name }
Dans l'exemple fourni, un pointeur vers une structure Admin est affecté à la variable user1 de type User. Cependant, lorsque user2 est créé en lui attribuant la valeur user1, les deux variables font référence à la même structure Admin sous-jacente. Par conséquent, changer le nom via user2 change également le nom via user1.
Création de copies distinctes
Pour créer des copies distinctes des valeurs d'interface, il existe plusieurs options :
1. Utilisation de l'assertion de type et de la copie de structure
Cette méthode consiste à affirmer la valeur dans user1, à créer une copie de la structure sous-jacente et à envelopper l'adresse de la copie dans une nouvelle valeur utilisateur :
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 user2.SetName("user2")
2. Utilisation de Reflection
Reflection peut être utilisée pour créer une nouvelle valeur du même type dynamique que la valeur d'interface, garantissant une copie complète. Voici comment :
var user3 User if reflect.TypeOf(user1).Kind() == reflect.Ptr { user3 = reflect.New(reflect.ValueOf(user1).Elem().Type()).Interface().(User) } else { user3 = reflect.New(reflect.TypeOf(user1)).Elem().Interface().(User) } user3.SetName("user3")
En copiant profondément la valeur de l'interface, nous créons une copie distincte qui peut être modifiée sans affecter l'original.
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!