Home >Backend Development >Golang >How to Achieve a Deep Copy of Interface Values in Go?
Deep Copy of Interface Values in Go
Copying an interface value directly in Go results in a shallow copy, meaning changes made to the copied value affect the original as well. This is because interfaces hold a reference to the underlying concrete type.
Cause of Name Change
To understand the issue in the provided code, let's analyze how interface values work. The User interface represents a contract, and both Admin and User implement this contract. When assigning user1 to user2, we're essentially creating a reference to the same Admin instance. Modifying user2's Name() method directly modifies the shared Admin instance, which consequently changes user1's name as well.
Solution with Reflection
To achieve a deep copy, we need to create a new instance of the underlying concrete type and wrap it in a new User interface value. One way to do this is to use reflection. We can use the reflect.ValueOf() and reflect.Elem() functions to get the underlying value stored in user1. Then, we can use reflect.New() to create a new instance of the same type and reflect.MethodByName() to obtain the Name() method. Finally, we can call the SetName() method on the new instance and wrap it in a new User interface value.
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) }
Using this function, we can create a copy that doesn't affect the original:
var user2 User = CloneUser(user1) user2.SetName("user2") fmt.Println(user1.Name(), user2.Name()) // Outputs: user1 user2
The above is the detailed content of How to Achieve a Deep Copy of Interface Values in Go?. For more information, please follow other related articles on the PHP Chinese website!