如何在 Go 中深度复制接口值
在 Go 中使用接口时,必须意识到接口持有对他们的潜在价值。修改接口值的副本也可能会无意中影响原始值。使用指向基础类型的指针创建接口值时通常会出现此问题。
理解问题
考虑以下用户界面:
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 }
在提供的示例中,指向 Admin 结构的指针被分配给 User 类型的 user1 变量。但是,当通过向 user1 分配值来创建 user2 时,这两个变量都引用相同的基础 Admin 结构。因此,通过 user2 更改名称也会通过 user1 更改名称。
创建不同副本
要创建接口值的不同副本,有以下几种选项:
1。使用类型断言和结构复制
此方法涉及对 user1 中的值进行类型断言,制作底层结构的副本,并将副本的地址包装在新的 User 值中:
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 user2.SetName("user2")
2。使用反射
反射可用于创建与接口值相同动态类型的新值,确保深拷贝。操作方法如下:
var user3 User if reflect.TypeOf(user1).Kind() == reflect.Ptr { user3 = reflect.New(reflect.ValueOf(user1).Elem().Type()).Interface().(User) } else { user3 = reflect.New(reflect.TypeOf(user1)).Elem().Interface().(User) } user3.SetName("user3")
通过深度复制接口值,我们创建一个不同的副本,可以在不影响原始值的情况下对其进行修改。
以上是如何在Go中深度复制接口值?的详细内容。更多信息请关注PHP中文网其他相关文章!