”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > ## 为什么我不能在 Go 中只复制带有指针接收器的类型实例?

## 为什么我不能在 Go 中只复制带有指针接收器的类型实例?

发布于2024-11-08
浏览:875

## Why Can\'t I Just Copy Instances of Types With Pointer Receivers in Go?

了解指针接收器和复制实例

在 Go 中,可以使用值接收器或指针接收器来定义方法。当类型 T 的所有方法都有 T 本身的接收者类型时,复制该类型的实例是安全的,因为调用其任何方法都必然会进行复制。

然而,当类型有带有指针接收器的方法。在这种情况下,应避免复制该类型的实例,因为它可能违反内部不变量。

复制指针的问题

让我们考虑一个示例来说明问题。假设我们有一个带有两个字段的类型 Wrapper:值 v 和指针 p。我们打算在 v 和 p 的指向值中存储相同的数字。为了确保这一点,我们提供了一个带有指针接收器的 Set 方法:

type Wrapper struct {
    v int
    p *int
}

func (w *Wrapper) Set(v int) {
    w.v = v
    *w.p = v
}

如果我们有一个Wrapper实例并调用Set方法,它将修改p的指向值。但是,如果我们创建实例的副本,则副本将与原始实例共享相同的指针值 p。这意味着对任一实例的任何后续方法调用都会影响两个副本。

示例:

a := Wrapper{v: 0, p: new(int)}
b := a

fmt.Printf("a.v=%d, a.p=%d;  b.v=%d, b.p=%d\n", a.v, *a.p, b.v, *b.p)

a.Set(1)
fmt.Printf("a.v=%d, a.p=%d;  b.v=%d, b.p=%d\n", a.v, *a.p, b.v, *b.p)

输出:

a.v=0, a.p=0;  b.v=0, b.p=0
a.v=1, a.p=1;  b.v=0, b.p=1

在此示例中,调用 a.Set(1) 后,b 的值无效,因为 b.v 不等于 *b.p。这是因为 a 和 b 中的指针 p 都指向相同的基础值。

为了避免此类问题,建议在使用带有指针接收器的方法时使用指针值。或者,如果该类型只能具有值接收器,则无论方法调用如何,复制该类型的实例都是安全的。

最新教程 更多>

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3