Array类型
数组在使用前必须声明长度,在golang中,数组属于值类型,在函数传递中,实际传递的是数组的拷贝并不是数组指针拷贝
Slice类型
是一种引用类型,它是不定长的,指向底层数组
Slice底层结构
type SliceHeader struct { Data uintptr #指向底层数组 Len int Cap int }
Slice 中len代表元素的个数,cap代表容量,在对slice进行append操作时,会导致slice的自动扩容。
切片扩容规则
1. 如果切片的容量小于1024个元素,那么扩容的时候slice的cap就翻番,乘以2;一旦元素个数超过1024个元素,增长因子就变成1.25,即每次增加原来容量的四分之一。
2. 如果扩容之后,还没有触及原数组的容量(系统分配的内存不够了),那么,切片中的指针指向的位置,就还是原数组,如果扩容之后,超过了原数组的容量,那么,Go就会开辟一块新的内存,把原来的值拷贝过来,这种情况丝毫不会影响到原数组。
nil切片和空切片的理解
func main() { var s1 []int s2 := make([]int,0) s4 := make([]int,0) fmt.Printf("s1 pointer:%+v, s2 pointer:%+v, s4 pointer:%+v, ", *(*reflect.SliceHeader)(unsafe.Pointer(&s1)),*(*reflect.SliceHeader)(unsafe.Pointer(&s2)),*(*reflect.SliceHeader)(unsafe.Pointer(&s4))) fmt.Printf("%v ", (*(*reflect.SliceHeader)(unsafe.Pointer(&s1))).Data==(*(*reflect.SliceHeader)(unsafe.Pointer(&s2))).Data) fmt.Printf("%v ", (*(*reflect.SliceHeader)(unsafe.Pointer(&s2))).Data==(*(*reflect.SliceHeader)(unsafe.Pointer(&s4))).Data) } #输出 s1 pointer:{Data:0 Len:0 Cap:0}, s2 pointer:{Data:824634207952 Len:0 Cap:0}, s4 pointer:{Data:824634207952 Len:0 Cap:0}, false //nil切片和空切片指向的数组地址不一样 true //两个空切片指向的数组地址是一样的,都是824634207952
nil切片和空切片指向的地址不一样。nil空切片引用数组指针地址为0(无指向任何实际地址)
空切片的引用数组指针地址是有的,且固定为一个值