最近做的项目用的语言是Go,写代码的过程无可避免就要使用到slice,因为是从Java转过来的,对于我来说,slice就是Java的ArrayList。
晚上读《Go语言实战》,对照写代码过程碰到的问题,发现slice有一些隐蔽的坑,记录一下,权当备忘。
slice是当作动态数组来使用,底层用的是数组,内部实现有3个field:
- 指向数组第一个元素的指针
- 切片长度(已有元素长度)
- 切片容量(最多能够容纳多少元素)
第一个坑:子切片和父切片用的是同一个底层数组
看代码:
pSlice := []int{0, 10, 20, 30, 40}
//新建一个子切片,指定元素为pSlice的index 1到3(不包括3),即{10, 20}
subSlice := pSlice[1:3]
这时候,改变subSlice的值,也会改动到pSlice
subSlice[1] = 22
pSlice索引为2的值也会变成22,这时候两个slice的值如下:
pSlice
{0, 10, 22, 30, 40}
subSlice
{10, 22}
如果对subSlice做append操作呢?
要知道,subSlice的长度是2,容量是4,append操作也会反映到pSlice
//append操作会返回一个新切片,同样共享底层数组
subSlice = append(subSlice, 33)
这时候两个slice的值如下:
pSlice
{0, 10, 22, 33, 40}
subSlice
{10, 22, 33}
你以为改的只是一个切片,其实,你改了人家全家啊!
第二个坑:for range遍历的是副本
遍历切片当然是用for range,简洁大方
slice := []string{"wo", "shi", "shui"}
for index, value := range slice {
println(&value)
println(&slice[index])
}
地址根本不一样啊!
在range中改值,你以为改变了他,其实他从来没变过,你只是改变了它