go中的slice坑

go中的slice坑

在进行项目中遇到了一些关于Go中的切片的坑,记录下来,提醒自己

在进行项目调试的时候,发现第一次请求时,能够拿到全部想要的结果。但是之后的所有请求,有一部分结果为空。但是整个方法在进行测试的时候都是能够通过的。不清楚错误是出在哪里。仔细回查代码,并没有感觉到哪里出现了问题。

在反复检查得都要爆炸的时候,突然感觉到了在一个方法中cipher []string作为参数传入应该会有问题。有了这个预感,就去验证自己的感觉是否是正确的。在对方法调用查询的时候发现,我是使用了一个全局的切片作为参数传入了该方法。于是做出猜想,普通的数组的传递是值传递,会不会是切片的传递其实是个引用传递。这样就能很好的解释了为什么 ,第一次请求能够拿到数据,之后的请求无法拿到数据:在这个方法中我对切片中的数据有移除的操作。如果是引用传递,那么这次移除操作操作的对象就是我所定义的全局的切片,导致全局的切片中的内容全部移除。之后的操作,全局切片中的内容就是空的。讲道理的,那么第二次极其以后的操作为空也就说的通了。但到底是不是猜测的那样,写了的demo来说明:

func main() {
    a := []int{1, 2, 3, 4}
    b := [4]int{1, 2, 3, 4}
    fmt.Println("origin slice: ", a)
    fmt.Println("origin array:", b)
    sliceTest(a)
    arrayTest(b)

    fmt.Println("change slice: ", a)
    fmt.Println("change array: ", b)
}

func sliceTest(slice []int) {
    slice[0] = 5
}

func arrayTest(array [4]int) {
    array[0] = 5
}

结果:

img

可以发现,通过sliceTest方法的确是修改了原始的a切片中的内容。虽然已经可以确定问题的原因,但是还是去网上验证一下。在segmentfault中的这篇关于Go语言中数组的参数传递问题写一个程序证明切片是值类型而map是引用类型的回答应该说的比较清楚了。讲道理,go的所有的传递都是值传递,slice是个值类型,但是表现出了引用语义。

问题既然发现了那就要进行解决。在学习go的时候记得go内置了一个copy()函数,用于复制内容。于是我很自然的想到了var一个切片变量,然后使用copy() 函数把传入的切片中的内容复制到这个新创建的变量中。想法是美好的,现实是残酷的。这样写的结果是:var出来的变量中的内容是空的。不能理解为什么是这个结果,于是去google了一把。在Why can not I copy a slice with copy in golang?(这个需要梯子)的回答中也讲明了:copy(dst,src) 复制min(len(dst), len(src))个元素,因为我们是直接使用var出来的dst的切片,因此len(dst)为0,即该方法什么都不做。因此不要使用var 申明一个变量,而是使用make()函数直接创建一个和src一样大小的切片:

arr := []int{1, 2, 3}
tmp := make([]int, len(arr))
copy(tmp, arr)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值