```````
testList := []uint16{1, 2, 3, 4}
myTest := testList //1.mytest 和 testList指向同一段
myTest = append(myTest, 9) //分离指向,所以在设计的时候最好给一个cap,不需要频繁的开辟内存
fmt.Println(testList)
```````
切片背后是数组,数组长度是不变的,切片长度是可变的。
切片背后可以看作是结构体,包含三部分:(数组第一个元素地址,len,cap)
`myTest := testList`这句话可以看作结构体的值拷贝,或者是结构体的指针拷贝(看背后具体实现)
append函数会生成带有三部分信息的结构体并返回,如果原切片内部的数组长度足够,那append返回的切片(结构体)内部的数组指向的还是原数组。如果append发现数组长度不够了,由于数组长度是不变的,肯定要重新分配一个更长的数组,把原数组东西拷贝过来,再append再返回,这时返回的切片(结构体)内部就是新数组了。
`myTest = append(myTest, 9)`这句话append生成了一个切片并返回,append是有返回值的,如果右边myTest内部数组长度足够,那右边结构体和左边内部是同一块数组,这里右边myTest内部数组长度不够,所以两边内部是不同的数组。
至于频繁的开辟内存问题,你可以看作cap不够时,一直把cap乘以2,这样指数级别的增长,其实不会很频繁。
假如调用两个函数,changeMap(map1) changeSlice(slice1),changeMap肯定是没有疑问,传进去引用类型map1,函数里面对map1修改,函数的调用者可以看到。而changeSlice虽然也是传入引用类型,但是由于append的特性,若函数里面调用了append,调用者可能会不知道发生了改变。此时可以使用slice1 = changeSlice(slice1),模仿内置的append函数(推荐),或者传入slice指针。
建议把The Go Programming Language 看一遍,绝对理解深刻。
#13
更多评论
<a href="/user/focusonline" title="@focusonline">@focusonline</a> 那请问range多重map[]map[]val呢,不注意么?
#2