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
Libérer: 2024-12-06 17:46:15
original
534 Les gens l'ont consulté

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
}
Copier après la connexion

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"}
Copier après la connexion

Maintenant, nous créons une nouvelle variable user2 et lui attribuons la valeur de user1.

var user2 User
user2 = user1
Copier après la connexion

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
Copier après la connexion

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)
}
Copier après la connexion

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!

source:php.cn
Déclaration de ce site Web
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal