douyou2368 2018-11-27 21:34
浏览 58
已采纳

Go编程语言中的struct的值接收器?

can someone explain to me why the output of r.a is empty as I have added a value of 2 into the list?

package main

import (
    "fmt"
)

func main() {
    var r R
    r.b = make(map[int]int)

    r.add()
    fmt.Println(r) // outputs {[] map[2:2]}
}

type R struct {
    a []int
    b map[int]int
}

func (r R) add()  {
    r.a = append(r.a, 2)
    r.b[2] = 2
}
  • 写回答

1条回答 默认 最新

  • dsbc80836 2018-11-27 21:51
    关注

    A short excerpt from the Tour of Go states that:

    Methods with pointer receivers can modify the value to which the receiver points [...]. Since methods often need to modify their receiver, pointer receivers are more common than value receivers.

    Why is r.b shown correctly while r.a is not modified at all?

    As already stated in my answer below, your add() method is a value receiver. Therefore, it will take your initialized struct (i.e. r), copy it and then modify it accordingly. Because you have initialized a new map under r.b in your main() function, here only the reference to this map is copied but not the whole map. Therefore, the manipulation on the map works but not on the slice r.a. But why does r.a not change at all? That's because append(), which is located in the add() method, stores a new slice header under your a property, and is pointing to a different section of the underlying array. At the end, your value receiver method add() made a copy of r, set a new slice header under the property a, and never changed the original struct r, that has been defined in the main() function as it was copied through the value receiver method add().

    In your case the add() method is a so called value receiver method that cannot do any manipulation on your defined struct r located in the main() function directly, but copies it and does the manipulation afterwards. Therefore, you need to turn your add() method into a pointer receiver method just like this:

    func (r *R) add()  {
        r.a = append(r.a, 2)
        r.b[2] = 2
    }
    

    Now the method is taking the actual reference of your struct r, that is initiated in the main() function, and modifies it accordingly.

    How could it work without changing your add() method to a pointer receiver?

    You simply would have to return the copied struct in your add() method like this:

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        var r R
        r.b = make(map[int]int)
        fmt.Println(r.add()) // outputs {[2] map[2:2]}
    }
    
    type R struct {
        a []int
        b map[int]int
    }
    
    func (r R) add() R {
        r.a = append(r.a, 2)
        r.b[2] = 2
        return r
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 Matlab问题解答有两个问题
  • ¥50 Oracle Kubernetes服务器集群主节点无法访问,工作节点可以访问
  • ¥15 LCD12864中文显示
  • ¥15 在使用CH341SER.EXE时不小心把所有驱动文件删除了怎么解决
  • ¥15 gsoap生成onvif框架
  • ¥15 有关sql server business intellige安装,包括SSDT、SSMS。
  • ¥15 stm32的can接口不能收发数据
  • ¥15 目标检测算法移植到arm开发板
  • ¥15 利用JD51设计温度报警系统
  • ¥15 快手联盟怎么快速的跑出建立模型