Heim >Backend-Entwicklung >Golang >Wie erreicht man eine tiefe Kopie der Schnittstellenwerte 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!