Go 为什么函数执行后值会发生变化?

Go 为什么函数执行后值会发生变化?,go,Go,我目前正在自学围棋,我很难理解某个行为: package main import ( "fmt" ) type List struct { n int } func (l List) Increment() { l.n += 1 l.LogState() // size: 1 } func (l List) LogState() { fmt.Printf("size: %v\n", l.n) } func main() { list :=

我目前正在自学围棋,我很难理解某个行为:

package main

import (
    "fmt"
)

type List struct {
    n int
}

func (l List) Increment() {
    l.n += 1
    l.LogState() // size: 1
}

func (l List) LogState() {
    fmt.Printf("size: %v\n", l.n)
}

func main() {
    list := List{}
    list.Increment()

    fmt.Println("----")
    list.LogState() // size: 0
}


LogState
执行两次。初始时间,在
Increment
调用期间,它打印
size:1
,但在
Increment
返回后,它打印
size:0
。为什么这些值不同?

使用
Increment
LogState
定义它们的方式,您只能使用
列表的值的副本。这意味着,如果在
Increment
函数中进行某些更改,则这些更改仅在
Increment
的函数范围内可见,并且仅在该特定范围的剩余部分可见。要确认始终使用初始
列表
值的副本,可以在同一函数内执行
增量
函数和
&l
之前记录
&List

如果要使更改永久化,则应使用指向内存地址的指针。这意味着您的函数应定义如下:

func (l *List) Increment()

func (l *List) LogState()

通过这种方式,您正在传递一个内存引用(指向内存中地址的指针),每次更改
l
的值时,您都会在传递的内存引用上更改它,并且它会反映到所有地方。

由于您没有使用指向结构的指针,所以节点未添加到原始linkedList的原因。因此,即使示例代码中的
Increment
函数更改了值。结构的副本更改为实际结构

可以使用指针接收器声明方法。这意味着 对于某些类型T,receiver type具有文本语法*T。(同样,T 本身不能是一个指针,如*int.)

如果要更改linkedlistNode结构计数器以显示添加到列表中的节点,则应在两种方法上使用指针类型接收器,以将链接列表修改为:

func (l *LinkedList) AddInitialValue(v interface{})
func (l *LinkedList) LogState()
并在主目录中向linkedList传递一个地址,以将这些指针类型接收器用作:

func main() {
    list :=  &LinkedList{}
    list.AddInitialValue(9)

    fmt.Println("----")
    list.LogState() // size: 0
}
工作代码

注意:-

使用指针接收器有两个原因

  • 修改其接收器指向的值
  • 避免在每个方法调用上复制值。如果接收器是一个大的结构,这可能会更有效
有关更多信息,请查看的可能重复项,以及更多信息。