Golang亿点小细节之slice
@Golang亿点小细节之切片 你所忽略的,往往才是Bug的起源
谨言
不会slice,请不要尝试用go写算法!
简单聊聊slice
slice是一个长度可变的数组 go提供给slice的主要方法包括有切片[:],重组[:len()+n],复制copy(),追加append() slice的三个部分:指向相关数组的指针ptr、当前数组长度len、相关数组最大容量cap 在开始下面的内容前,请把这个图记在脑子里!
首先我们先来聊聊切片操作
x:=[]int{ 2,3,5,7,11} y:=x[1:3] //y是通过对x进行切片得到的
但是切片不是进行拷贝,谨记,看图 切片操作是将产生的slice的ptr指向原slice的相关数组,同时通过len和cap产生一个形式上的切片
接下来聊聊重组和复制
改变slice长度的过程叫做重组
sl = sl[0:len(sl)+1]
slice重组只是改变了len的值,切片可以反复扩展直到占据整个相关数组,即len=cap,当len>cap是就会发生扩容,扩容是使ptr重新指向一个更大的相关数组 slice复制 func copy(dst, src []T) int copy 将类型为 T 的切片从源地址 src 拷贝到目标地址 dst,覆盖 dst 的相关元素,并且返回拷贝的元素个数。一般情况下复制可以使得两个slice拥有相互独立的相关数组。不过,源地址和目标地址可能会有重叠
我愿称append()是go最大的坑
先给大家上一段代码
package main import "fmt" func main() { x :=[]int{ 2,3,5,7,11} y := x[1:3] fmt.Println(y) y=append(y, 10) fmt.Println(y) fmt.Println(x) /* output: [3 5] [3 5 10] [2 3 5 10 11] //我的7怎么变成了10????????? */ }
细心的小伙伴会发现7->10,原因是因为y.ptr指向了x[1],所以append()把7给覆盖掉了 在来一段代码
package main import "fmt" func main() { x :=[]int{ 2,3,5,7,11} y := x[1:] // 通过修改切片操作的长度,使得y在进行追加时会发生扩容 fmt.Println(y) y=append(y, 10) fmt.Println(y) fmt.Println(x) /* output: [3 5 7 11] [3 5 7 11 10] [2 3 5 7 11] // 我的7怎么又回来了??????? */ }
上文中说到当slice发生扩容时,会重新分配相关数组,所以y的相关数组被重新分配了,但是这并不会影响x