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 PADS Logic 原理图
  • ¥15 PADS Logic 图标
  • ¥15 电脑和power bi环境都是英文如何将日期层次结构转换成英文
  • ¥20 气象站点数据求取中~
  • ¥15 如何获取APP内弹出的网址链接
  • ¥15 wifi 图标不见了 不知道怎么办 上不了网 变成小地球了
  • ¥50 STM32单片机传感器读取错误
  • ¥15 (关键词-阻抗匹配,HFSS,RFID标签天线)
  • ¥15 机器人轨迹规划相关问题
  • ¥15 word样式右侧翻页键消失