Maison >développement back-end >Golang >Comment obtenir une copie approfondie des valeurs d'interface dans Go ?

Comment obtenir une copie approfondie des valeurs d'interface dans Go ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-12-07 20:57:12798parcourir

How to Achieve a Deep Copy of Interface Values in Go?

Copie approfondie des valeurs d'interface dans Go

La copie d'une valeur d'interface directement dans Go entraîne une copie superficielle, ce qui signifie que les modifications apportées à la valeur copiée La valeur affecte également l'original. En effet, les interfaces contiennent une référence au type concret sous-jacent.

Cause du changement de nom

Pour comprendre le problème dans le code fourni, analysons le fonctionnement des valeurs d'interface. . L'interface utilisateur représente un contrat, et l'administrateur et l'utilisateur mettent en œuvre ce contrat. Lors de l'attribution de user1 à user2, nous créons essentiellement une référence à la même instance d'administration. La modification de la méthode Name() de l'utilisateur 2 modifie directement l'instance d'administration partagée, ce qui modifie par conséquent également le nom de l'utilisateur 1.

Solution avec réflexion

Pour obtenir une copie complète, nous avons besoin pour créer une nouvelle instance du type concret sous-jacent et l'envelopper dans une nouvelle valeur d'interface utilisateur. Une façon d’y parvenir est d’utiliser la réflexion. Nous pouvons utiliser les fonctions réflexion.ValueOf() et réflexion.Elem() pour obtenir la valeur sous-jacente stockée dans user1. Ensuite, nous pouvons utiliser Reflect.New() pour créer une nouvelle instance du même type et Reflect.MethodByName() pour obtenir la méthode Name(). Enfin, nous pouvons appeler la méthode SetName() sur la nouvelle instance et l'envelopper dans une nouvelle valeur d'interface utilisateur.

func CloneUser(user User) User {
    val := reflect.ValueOf(user)
    if val.Kind() != reflect.Ptr {
        panic("expected pointer")
    }
    elem := val.Elem()
    t := elem.Type()
    newElem := reflect.New(t).Elem()
    newElem.MethodByName("SetName").Call([]reflect.Value{reflect.ValueOf(newElem.String())})
    return newElem.Interface().(User)
}

En utilisant cette fonction, nous pouvons créer une copie qui n'affecte pas l'original :

var user2 User = CloneUser(user1)
user2.SetName("user2")
fmt.Println(user1.Name(), user2.Name()) // Outputs: user1 user2

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