golang:重新分配指针方法接收器

Hon*_*oon 10 go

我对指针方法接收器和非指针方法接收器的理解首先是可以在方法中修改而下一个不是.

因此,以下工作正如我预期的那样.

type student struct {
    name string
    age  int
}

func (s *student) update() {
    s.name = "unknown"
    s.age = 0
}

func main() {
    s := student{"hongseok", 13}
    fmt.Println(s)

    s.update()
    fmt.Println(s)
}
Run Code Online (Sandbox Code Playgroud)

它打印hongseok/13unknown/0.

但是,我想通过重新分配立即替换update方法中的整个s.所以,我刚刚修改了更新方法.

func (s *student) update() {
    s = &student{"unknown", 0}
}
Run Code Online (Sandbox Code Playgroud)

并且它不会在main方法中更改s并打印double hongseok/13.

func (s *student) update() {
    *s = student{"unknown", 0}
}
Run Code Online (Sandbox Code Playgroud)

以上更改解决了问题.

我认为没有语义差异.我错过了什么?

Jim*_*imB 28

在第一个例子中:

func (s *student) update() {
    s = &student{"unknown", 0}
}
Run Code Online (Sandbox Code Playgroud)

您正在为新值指定一个全新的"指针值" s,并将新*s点指定为新student值.该变量s仅限于方法体,因此返回后没有副作用.

在第二个例子中

func (s *student) update() {
    *s = student{"unknown", 0}
}
Run Code Online (Sandbox Code Playgroud)

您正在取消引用s,并将值更改*s为指向新student值,或者换句话说,您将students点的地址处添加新值.


eva*_*nal 6

在此示例中,您将存储的地址更改s为不同的值;

func (s *student) update() {
    s = &student{"unknown", 0}
}
Run Code Online (Sandbox Code Playgroud)

虽然使用指针被视为“通过引用传递”,但引用本身是一个与推送到调用堆栈上的任何其他值一样的值。当您返回 main 时, 的值s就是该范围内的值。因此,为了给出更具体的内容,您调用了 main s = 1(为了简单起见,调用了地址 1 和 2),在该方法中,您分配了一个student位于地址 2 的新值,并设置了s = 2,当您返回该版本时,该版本s将从堆栈中弹出,并且s主要观点1没有改变。

在后一个例子中;

func (s *student) update() {
    *s = student{"unknown", 0}
}
Run Code Online (Sandbox Code Playgroud)

您正在取消引用s并将新对象分配给该位置,从而覆盖现有内存。当您返回 main 中的指针仍然指向同一位置,但内存中该位置有不同的数据。因此,在本示例中,您正在编写一个新student实例来寻址1,因此当您返回时,您会在调用范围中看到新值。