1.长度和容量的含义
切片的
长度len()是它所包含的元素实际个数。
切片的容量cap()是从它的第一个元素到其【底层数组/切片】最后一个元素的个数。
func f1() {
array := [10]int32{1, 2, 3, 4, 5} //[1,2,3,4,5,0,0,0,0,0]
temp := make([]string, 0)
ss := []string{"武汉", "西安", "苏州"}
temp = append(temp, ss...) //...的意思是将上面的string数组拆开挨个放到ss位置上
fmt.Println(temp, len(temp), cap(temp))
s1 := array[:5] //【左闭右开原则】所以是:0-4角标=[1,2,3,4,5]
//s1是从array数组身上切来的,那么【底层数组】就是array
//s1的第一个元素是1,array的最后一个元素是角标9号的0,对应在array数组中,容量计算出就是10
fmt.Println(s1, len(s1), cap(s1)) //[1,2,3,4,5],5,10
s2 := s1[5:10] //明显 s1 拿不到数据,所以都赋值为0,[0,0,0,0,0]
fmt.Println(s2)
}
2.扩容是深拷贝,那容量机制是???
1.若新申请容量(newcap)新增了1倍还多的旧容量(oldcap),最终容量(newcap)就是新申请的容量(cap)
2.1否则判断,如果 oldlen<1024,则最终容量(newcap)就是旧容量(oldcap)的两倍
2.2否则判断,如果 oldlen>1024,则最终容量(newcap)从旧容量(oldcap)开始循环增加原来的1/4 直到最终容量(newcap)大于等于新申请的容量(cap),即(newcap >= cap)
3.如果最终容量(cap)计算值溢出,则最终容量(cap)就是新申请容量(newcap)注意:切片扩容会根据元素的类型而做不同的处理,比如int和string类型的处理方式就不一样
func f2() {
array := [10]int32{1, 2, 3, 4, 5}
s1 := array[:5:5] //【左闭右开原则】所以是:0-4角标=[1,2,3,4,5],容量参数为5,实际容量为5-0=5
s2 := array[:5:10] //明显 s1 拿不到数据,所以都赋值为0,[0,0,0,0,0],容量参数为10,实际容量为10-5=5
fmt.Println(s1, len(s1), cap(s1))//[1 2 3 4 5] 5 5
fmt.Println(s2, len(s2), cap(s2))//[1 2 3 4 5] 5 10
fmt.Printf("%p\n", s1)
s1 = append(s1, 6) //因为s1的是5,原本是没法追加的,所以要深拷贝一份再追加
fmt.Println(s1, len(s1), cap(s1)) //[1,2,3,4,5,6],6,12【这里的12不应该是10???】
fmt.Printf("%p\n", s1) //会发现s1的地址发生了变化,说明s1扩容是重新找的地址,开一块新的空间
a1 := []int{1, 2, 3}
fmt.Println(a1, len(a1), cap(a1)) //[1 2 3] 3 3
a1 = append(a1, 5)
fmt.Println(a1, len(a1), cap(a1)) //[1 2 3 5] 4 6
}
s1 的长度,容量不应该是 6 10 ???
看下面对比:
func main() {
array := [10]int32{1, 2, 3, 4, 5}
s1 := array[:5:5] //【左闭右开原则】所以是:0-4角标=[1,2,3,4,5],容量参数为5,实际容量为5-0=5
fmt.Println(s1, len(s1), cap(s1)) //[1 2 3 4 5] 5 5
s1 = append(s1, 6) //因为s1的是5,原本是没法追加的,所以要深拷贝一份再追加
fmt.Println(s1, len(s1), cap(s1)) //[1,2,3,4,5,6],6,12
s2 := array[:5] //【左闭右开原则】所以是:0-4角标=[1,2,3,4,5]
fmt.Println(s2, len(s2), cap(s2)) //[1 2 3 4 5] 5 5
s2 = append(s2, 6) //因为s1的是5,原本是没法追加的,所以要深拷贝一份再追加
fmt.Println(s2, len(s2), cap(s2)) //[1,2,3,4,5,6],6,10
}
发现不同就是因为s1在截取array的时候有没有设定容量参数
所以:不设置容量参数才是符合扩容机制的