首页 > 后端开发 > Golang > 如何正确复制Go中的接口值以避免共享底层数据?

如何正确复制Go中的接口值以避免共享底层数据?

Barbara Streisand
发布: 2024-12-06 17:46:15
原创
533 人浏览过

How to Properly Copy Interface Values in Go to Avoid Shared Underlying Data?

在 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 界面。我们创建一个 User 类型的 user1 变量,并使用指向 Admin 结构体的指针对其进行初始化。

var user1 User
user1 = &Admin{name: "user1"}
登录后复制

现在,我们创建一个新的 user2 变量并将其分配给 user1 的值。

var user2 User
user2 = user1
登录后复制

这里的问题是 user1 和 user2 都引用同一个 Admin 实例。更改 user2 的名称也会更改 user1 的名称。这是因为接口值仅包含指向底层 Admin 结构体的指针。

为了防止这种情况,我们需要为 user2 创建一个新的 Admin 结构体。我们可以使用反射来完成这个:

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 的名称不再影响 user1。

但是,这个解决方案需要我们知道接口值的具体类型提前。更通用的解决方案是使用反射来创建接口值动态类型的新实例:

var user2 User
if reflect.TypeOf(user1).Kind() == reflect.Ptr {
    // Pointer:
    user2 = reflect.New(reflect.ValueOf(user1).Elem().Type()).Interface().(User)
} else {
    // Not pointer:
    user2 = reflect.New(reflect.TypeOf(user1)).Elem().Interface().(User)
}
登录后复制

此解决方案适用于指针和非指针接口值。

以上是如何正确复制Go中的接口值以避免共享底层数据?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板