当命名类型为T的任何方法具有指针接收器时,复制类型T的实例

当命名类型为T的任何方法具有指针接收器时,复制类型T的实例,第1张

当命名类型为T的任何方法具有指针接收器时,复制类型T的实例

调用方法时,将首先复制调用该方法的值,然后将该副本传递/用作接收方。

如果类型仅具有带有值接收器的方法,则意味着无论方法内部执行什么 *** 作,也无论您(或其他任何人)调用什么方法,这些方法都将无法更改 原始
值,因为–如前所述上面-仅传递副本,并且该方法只能修改副本-而不是原始副本。

因此,这意味着如果您复制该值,则不必担心,原始文件或副本上调用的方法都不会/不会修改该值。

否,当类型具有带有指针接收器的方法时。如果方法具有指针接收器,则该方法可以更改/修改 指向的 值,该值不是副本,而是原始值(仅 指针
是副本,但指向原始值)。

让我们来看一个例子。我们创建一个

int
包装器类型,其中包含2个字段:an
int
和an
*int
。我们打算在两个字段中存储相同的数字,但是一个是指针(并且我们将其存储
int
指向的 值中):

type Wrapper struct {    v int    p *int}

为确保两个值(

v
*p
)相同,我们提供了
Set()
一种设置两个值的方法:

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

Wrapper.Set()
具有指针接收器(
*Wrapper
),因为它必须修改值(类型为
Wrapper
)。无论我们传递给哪个数字
Set()
,我们都可以确保一旦
Set()
返回,两者
v
*p
将相同,并且等于传递给的数字
Set()

现在,如果我们的值为

Wrapper

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

我们可以

Set()
在上面调用该方法:

a.Set(1)

编译器将自动采用的地址

a
作为接收器,因此上述代码表示
(&a).Set(1)

如果只使用方法来更改字段的值,我们希望任何类型的值

Wrapper
Wrapper.v
和中都具有相同的数字。
*Wrapper.pv``Set()

现在,让我们看一下如果我们复制的问题

a

a := Wrapper{v: 0, p: new(int)}b := afmt.Printf("a.v=%d, a.p=%d;  b.v=%d, b.p=%dn", a.v, *a.p, b.v, *b.p)a.Set(1)fmt.Printf("a.v=%d, a.p=%d;  b.v=%d, b.p=%dn", a.v, *a.p, b.v, *b.p)

输出(在Go Playground上尝试):

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

我们制作了一个副本

a
(将其存储在中
b
),并打印了值。到目前为止,一切都很好。然后我们调用
a.Set(1)
,之后它
a
仍然很好,但是的内部状态
b
变为无效:
b.v
不再等于
*b.p
。解释很明确:当我们复制
a
(是一种
struct
类型)时,将复制其字段的值(包括指针
p
),并且in中的指针
b
将指向与in中的指针相同的值
a
。因此,修改指标值将影响的两个副本
Wrapper
,但我们有2个不同的
v
字段(它们是非指标)。

如果您有使用指针接收器的方法,则应使用指针值。

请注意,如果您复制一个的值

*Wrapper
,那么一切仍然会很酷:

a := &Wrapper{v: 0, p: new(int)}b := afmt.Printf("a.v=%d, a.p=%d;  b.v=%d, b.p=%dn", a.v, *a.p, b.v, *b.p)a.Set(1)fmt.Printf("a.v=%d, a.p=%d;  b.v=%d, b.p=%dn", a.v, *a.p, b.v, *b.p)

输出(在Go Playground上尝试):

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

在这种情况下

a
是一个指针,它的类型是
*Wrapper
。我们做它的一个副本(其存储在
b
),被称为
a.Set()
,以及两者的内部状态
a
b
仍然有效。这里我们只有一个
Wrapper
值,
a
只保存一个指向它的指针(它的地址)。复制时
a
,我们只会复制指针值,而不复制
struct
值(类型
Wrapper
)。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5170655.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-18
下一篇 2022-11-18

发表评论

登录后才能评论

评论列表(0条)

保存