Go - 方法接收者类型为 T 与 *T的区别

自定义类型方法如下
type cInt []int

func (c cInt) appendV(v int) {
        c = append(c,v)
}

func (c *cInt) appendP(v int)  {
        *c = append(*c,v)
}
测试使用数据
  c := cInt{2,3}
  c.appendV(4)
  c.appendV(5)
  c.appendV(6)
  fmt.Printf("after appendV :%v \n",c)

  c.appendP(9)
  c.appendP(10)
  c.appendP(11)
  fmt.Printf("after appendP :%v \n",c)
测试结果如下
-----------------------------
after appendV :[2 3] 
after appendP :[2 3 9 10 11] 

自己理解的产生原因:

把实参传递给 类型T : 相当于把Slice指向的底层数组的首地址传给虚参
所以在方法内执行c = append(c, v)的时候 分配新的空间,复制c的内容到这个空间中,再添加v,最会把这个新的slice 地址赋值给 c, 而c是局部的变量,出了这个函数之后要被回收,随机这个新的slice 也就被回收,所以append的时候不能添加.

把实参传递给 类型*T : 相当于把指向Slice的变量的地址传给虚参
所以在方法内执行c = append(c, v)的时候 分配新的空间,复制c的内容到这个空间中,再添加v,最会把这个新的slice 地址赋值给 c, 相当于把外部变量的指向这个新的Slice

另一个和Slice,Array 相关的内容
type cInt []int

func (c cInt) zeroValue() {
        for i := range c {
                c[i] = 0
        }
}

func main() {
        fmt.Printf("-------------------\n")
        v := cInt{1,2,3,4,5,6}
        fmt.Printf("v:%v \n",v)
        v.zeroValue()
        fmt.Printf("v:%v \n",v)
        fmt.Printf("-------------------\n")
}
结果为:
-------------------
v:[1 2 3 4 5 6] 
v:[0 0 0 0 0 0] 
-------------------
Other
  1. 上面仅仅是自己的理解,可能存在偏差或者理解错误,望请指正.
  2. 如果你有发现有更多的坑 可以在下面给出,相互学习,感谢在先.
阅读 3.7k
2 个回答

关于appendV,使用值接收者声明方法,调用时会使用这个值的一个副本来执行
关于appendP,调用使用指针接收者声明的方法时,这个方法会共享调用方法时接收者所指向的值,可以理解为go做了如下调整:

c.appendP(9) -> (&c).appendP(9) 

共享值,故可以改变

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题