问题
- 函数传参了一个slice,在函数内触发了对长度的修改(添加或删除),但是未影响函数外的实参
- 由此产生了另一个问题,我们用map在函数内修改会不会有影响不到实参的情况?
结论
-
map作为函数参数时是引用传递,操作的始终是同一个对象
-
slice作为函数参数时是引用传递。但是若函数内部对slice参数有append赋值时,则不再是同一个对象
过程
其实上面的问题与两点有关
- golang只有值传递
- map在源码中实际是一个指向hmap的指针,但是slice实际是一个struct
type SliceHeader struct {
Data unitptr
Len int
Cap int
}
这样当我们通过切片进行函数传参的时候,实际长底下的样子
由于是值拷贝,所以形参只是把Data的值(一个地址),Len和Cap的值copy了过来,这样当触发了长度变化的时候,Len的变化不会影响到实参,Data再重新扩容后也会指向新的地方,所以会带来上面的问题
那么map为啥没这个问题呢?因为map本身就是一个指针,值拷贝的结果是下图这样的
而map本身在扩容的时候是直接修改的hmap中的老桶和新桶,那么当对形参进行修改的时候,由于他俩的指向同一个位置,所以即使我们在函数内触发了扩容,对外面也没有影响
抛砖引玉
参考:
https://www.cnblogs.com/beatle-go/p/17898561.html
https://blog.csdn.net/ezreal_pan/article/details/132106944
https://blog.csdn.net/vince1998/article/details/137073224
https://blog.csdn.net/yzf279533105/article/details/89461651
https://www.idc.net/help/333207/