golang slice作为函数参数应注意的问题

表面上看,slice作为参数的时候传递的是引用,在函数中对slice的修改在函数返回以后才能看到。但是其实,golang里面所有的参数传递都是传值,slice也不例外,只不过slice的值是一个header,slice传值传的是SliceHeader:

type SliceHeader struct {
    Data uintptr
    Len  int
    Cap  int
}

其中Data为一个指针,指向slice对应的数组,Len记录数组的大小,Cap记录数组实际占用的内存空间。当slice作为参数调用函数的时候,实参slice和形参slice的Data指向相同的内存区域。但是,如果在函数中修改了slice的长度,这个修改是不会被记录的。例如:

func main(){
    s:=make([]int,1,1)
    f(s)
    fmt.Println(len(s))
}
func f(x []byte){
    x=append(x,1)
}

在main函数中,s的Data初始指向一个数组,Len和Cap也为1。

调用f的时候,s的SliceHeader传递给x,x的Data和s的Data指向同一内存区域,x的Len和Cap为1

这个时候,向x添加一个元素,系统会重新分配内存存储新数组,x的Data指向新数组,xLen和Cap变成2,但是s的指针还指向原来的内存区域,并且Cap和Len仍然为1,此时如果引用第二个元素s[1]会报index out of range 的错误。

ps:个人推测golang里面map应该也可能存在类似的问题,不过我现在还没有验证。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值