为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕标5832272 2023-04-24 16:03:57
我目前正在自学围棋,但我无法理解某种行为:package mainimport (    "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}https://play.golang.org/p/-O24DiNPkxxLogState被执行两次。最初,在Increment通话期间,它打印size: 1但Increment返回后打印size: 0。为什么这些值不同?
查看完整描述

2 回答

?
ITMISS

TA贡献1871条经验 获得超8个赞

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

您可以使用指针接收器声明方法。这意味着接收者类型对于某些类型 T 具有文字语法 *T。(此外,T 本身不能是指针,例如 *int。)

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

func (l *LinkedList) AddInitialValue(v interface{})
func (l *LinkedList) LogState()

并在 main 内部将地址传递给 linkedList 以将这些指针类型接收器用作:

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

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

笔记:-

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

  • 修改其接收者指向的值。

  • 避免在每次方法调用时复制值。如果接收者是一个大结构,这会更有效


查看完整回答
反对 回复 2023-04-24
?
喵喔喔

TA贡献1735条经验 获得超5个赞

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

如果你想让更改永久化,你应该使用指向内存地址的指针。这意味着你的函数应该这样定义:

func (l *List) Increment()
func (l *List) LogState()

这样,您将传递一个内存引用(指向内存中地址的指针),并且每次更改 的值时l,您都会在传递的内存引用上更改它,并且它会在任何地方反映出来。


查看完整回答
反对 回复 2023-04-24
  • 2 回答
  • 0 关注
  • 123 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信