切片
创建时指定切片长度和容量:
make([]int, 1, 10) 创建一个长度为1容量为10的[]int类型切片
在切片的底层数据结构中,会存在一个底层数组,切片可以看作对底层数组的某个片段的引用。
来看下面这个例子:
s1 := []int{1, 2, 3, 4, 5}
s2 := s1[2:5]
fmt.Printf("s1 : %d len: %d cap: %d \n", s1, len(s1), cap(s1))
fmt.Printf("s2 : %d len: %d cap: %d", s2, len(s2), cap(s2))
输出结果为:
s1 : [1 2 3 4 5] len: 5 cap: 5
s2 : [3 4 5] len: 3 cap: 3
在这个例子里,使用切片表达式初始化s2,[2:5]转化成我们数学的集合表示为:[2,5)即包含了索引第二的元素,不包含索引为5的元素。并且长度和容量会重新初始化,但是他们指向的底层数组都是同一个,s1如果进行了某种更改同时会影响到s2。
例如:
s1 := []int{1, 2, 3, 4, 5}
s2 := s1[2:5]
s1[2] = 10
fmt.Printf("s1 : %d len: %d cap: %d \n", s1, len(s1), cap(s1))
fmt.Printf("s2 : %d len: %d cap: %d", s2, len(s2), cap(s2))
输出结果为:
s1 : [1 2 10 4 5] len: 5 cap: 5
s2 : [10 4 5] len: 3 cap: 3
copy函数
copy(s1, s2)
s1:目标切片 s2:源切片
用于将内容从一个切片复制到另一个切片。两个数组切片不一样大,就会按其中较小的那个数组切片的元素个数进行复制。
一个例子:
s1 := []int{1, 2, 3, 4, 5}
//var s2 []int
s2 := make([]int, 5, 5)
copy(s2, s1[2:5])
s1[2] = 10
fmt.Printf("s1 : %d len: %d cap: %d \n", s1, len(s1), cap(s1))
fmt.Printf("s2 : %d len: %d cap: %d", s2, len(s2), cap(s2))
输出结果为:
s1 : [1 2 10 4 5] len: 5 cap: 5
s2 : [3 4 5 0 0] len: 5 cap: 5
我们使用copy来复制切片的时候,需要先初始化目标切片的长度,如果var s2 []int 这种形式来定义,则运行copy函数后s2还是为空切片[]。
使用copy函数后,s2就指向了一个新的底层数组,我们对s1的操作也就影响不到s2了。
扩容
当切片容量满,继续添加元素的时候,会触发扩容机制,扩容后的切片指向了一个新的数组,并不是对原底层数组进行了更改。
s1 := []int{1, 2, 3, 4, 5}
s2 := s1[2:5]
s2 = append(s2, 6, 7)
s1[2] = 10
fmt.Printf("s1 : %d len: %d cap: %d \n", s1, len(s1), cap(s1))
fmt.Printf("s2 : %d len: %d cap: %d", s2, len(s2), cap(s2))
输出结果为:
s1 : [1 2 10 4 5] len: 5 cap: 5
s2 : [3 4 5 6 7] len: 5 cap: 6
可以看到,对s1的更改并没有对s2产生影响,因为它们指向的不是同一个底层数组了。