Maison >développement back-end >Golang >Comment copier correctement les valeurs de l'interface dans Go pour éviter le partage des données sous-jacentes ?

Comment copier correctement les valeurs de l'interface dans Go pour éviter le partage des données sous-jacentes ?

Barbara Streisand
Barbara Streisandoriginal
2024-12-06 17:46:15561parcourir

How to Properly Copy Interface Values in Go to Avoid Shared Underlying Data?

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn