天天看点

Go语言的切片操作对底层数组的影响

通过数组或切片生成新的切片时,修改新切片可能会影响原有的数组或切片。直接上代码:

package main
import (
	"fmt"
)

func main(){

	// array是数组
	array:=[...]int{1,2,3,4,5,6,7,8,9}
	fmt.Printf("数组array的长度是%d,容量是%d\n", len(array), cap(array))

	// slice是切片,定义时其实是指向数组array的引用,容量由原数组的最后一个元素位置决定
	slice:=array[2:4]
	fmt.Printf("切片slice的长度是%d,容量是%d\n", len(slice), cap(slice))

	// slice切片追加一个元素,因为现有的容量(7)仍然能够满足追加后的空间需求(3),
	// 所以切片不会扩容,对应的引用地址就不会变化
	slice[0]=99
	slice= append(slice, 123)

	fmt.Printf("切片追加1个新元素后,原数组的值%+v\n",array)
	fmt.Printf("切片追加1个新元素后,切片的值%+v,容量是%d\n",slice, cap(slice))

	// slice切片追加一个切片(5个元素),因为现有的容量(7)将不能满足追加后的空间需求(8),
	// 所以切片会扩容(*2倍),对应的引用地址将发生变化(不再指向原数组)
	slice= append(slice,[]int{11,22,33,44,55}...)
	fmt.Printf("切片追加新元素后,切片的值%+v,容量是%d\n",slice, cap(slice))
	fmt.Printf("切片追加新元素后,原数组的值%+v\n",array)
}

           

结果:

数组array的长度是9,容量是9
切片slice的长度是2,容量是7
切片追加1个新元素后,原数组的值[1 2 99 4 123 6 7 8 9]
切片追加1个新元素后,切片的值[99 4 123],容量是7
切片追加新元素后,切片的值[99 4 123 11 22 33 44 55],容量是14
切片追加新元素后,原数组的值[1 2 99 4 123 6 7 8 9]
           

分析:

 原数组一共有7个元素,数组的len和cap均为7;

定义的切片,len为2,cap为7(重点:7是根据原数组的元素计算而来),此时切片其实是引用的原数组地址,修改切片的第1个元素值为99,其实就是修改了原数组;

向切片追加1个新元素123,追加后的切片len将是3,此时切片现有的cap为7,是能够满足追加需求的,所以切片不会扩容,对应的也就不会重新分配新地址,追加的元素将直接覆盖原数组;

继续向切片追加1个切片(5个元素),追加后的切片len将是8,将超过现有cap(7),所以此次追加将导致切片扩容,重新分配新的空间。追加行为将在新的地址空间里发生,对原数组将不产生影响,追加后的切片cap将*2倍(2*7=14);

如果将原数组改成切片,效果是一样的。定义切片的代码将是:

array:=[]int{1,2,3,4,5,6,7,8,9}