Heim >Backend-Entwicklung >Golang >Wie erreicht man eine tiefe Kopie der Schnittstellenwerte in Go?

Wie erreicht man eine tiefe Kopie der Schnittstellenwerte in Go?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-12-07 20:57:12739Durchsuche

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

Tiefe Kopie von Schnittstellenwerten in Go

Das direkte Kopieren eines Schnittstellenwerts in Go führt zu einer flachen Kopie, d. h. Änderungen an den kopierten Werten Der Wert wirkt sich auch auf das Original aus. Dies liegt daran, dass Schnittstellen einen Verweis auf den zugrunde liegenden konkreten Typ enthalten.

Ursache der Namensänderung

Um das Problem im bereitgestellten Code zu verstehen, analysieren wir, wie Schnittstellenwerte funktionieren . Die Benutzeroberfläche stellt einen Vertrag dar, und sowohl der Administrator als auch der Benutzer implementieren diesen Vertrag. Wenn wir Benutzer1 Benutzer2 zuweisen, erstellen wir im Wesentlichen einen Verweis auf dieselbe Admin-Instanz. Durch Ändern der Name()-Methode von Benutzer2 wird direkt die gemeinsam genutzte Admin-Instanz geändert, wodurch sich folglich auch der Name von Benutzer1 ändert.

Lösung mit Reflection

Um eine tiefe Kopie zu erreichen, benötigen wir um eine neue Instanz des zugrunde liegenden konkreten Typs zu erstellen und sie in einen neuen Benutzeroberflächenwert einzuschließen. Eine Möglichkeit hierfür ist die Reflexion. Wir können die Funktionen „reflect.ValueOf()“ und „reflect.Elem()“ verwenden, um den zugrunde liegenden Wert abzurufen, der in Benutzer1 gespeichert ist. Anschließend können wir „reflect.New()“ verwenden, um eine neue Instanz desselben Typs zu erstellen, und „reflect.MethodByName()“ verwenden, um die Methode „Name()“ abzurufen. Schließlich können wir die SetName()-Methode für die neue Instanz aufrufen und sie in einen neuen Benutzeroberflächenwert einschließen.

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)
}

Mit dieser Funktion können wir eine Kopie erstellen, die keine Auswirkungen auf das Original hat:

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

Das obige ist der detaillierte Inhalt vonWie erreicht man eine tiefe Kopie der Schnittstellenwerte in Go?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn