区别
1.数组长度固定,切片长度可变
2.数组是深拷贝,切片是浅拷贝,切片是引用类型
扩容规则 不同版本不一样
https://www.jb51.net/article/280481.htm#_lab2_2_1
go1.18
1.如果期望容量大于当前容量的两倍就会使用期望容量;
2.如果当前切片的容量小于阈值(默认 256)就会将容量翻倍;
3.如果当前切片的容量大于等于阈值(默认 256),小切片的2倍生长,大切片生长1.25倍;
package mainimport "fmt"func main() {arr1 := [3]int{1, 2, 3}arr2 := arr1fmt.Printf("%p\n", &arr1[0])fmt.Printf("%p\n", &arr2[0])arr2[0] = 10fmt.Println(arr1)fmt.Println(arr2)sli1 := []int{1, 2}sli2 := sli1fmt.Printf("%p\n", &sli1[0])fmt.Printf("%p\n", &sli2[0])sli2[0] = 10fmt.Println(sli1)fmt.Println(sli2)sliceAppend(sli1)fmt.Println(sli1)
}// 不会改变原有slice长度
func sliceAppend(s []int) {s = append(s, []int{2, 2, 2}...)fmt.Printf("sliceAppend %d %d\n", len(s), len(s))
}
package mainimport "fmt"func main() {sli1 := []int{1}fmt.Printf("len=%d cap=%d\n", len(sli1), cap(sli1))// 期望容量大于当前容量的两倍sli1 = append(sli1, []int{2, 3, 4}...)fmt.Printf("len=%d cap=%d\n", len(sli1), cap(sli1))// 如果当前切片的容量小于阈值(默认 256)就会将容量翻倍sli1 = append(sli1, 1)fmt.Printf("len=%d cap=%d\n", len(sli1), cap(sli1))// 如果当前切片的容量大于等于阈值(默认 256),就会每次增加 25% 的容量/*//从小切片的2倍生长过渡//大切片生长1.25倍newcap += (newcap + 3*threshold) / 4*/sli2 := make([]int, 256, 256)fmt.Printf("len=%d cap=%d\n", len(sli2), cap(sli2))sli2 = append(sli2, 1)fmt.Printf("len=%d cap=%d\n", len(sli2), cap(sli2))for i := 0; i < 10; i++ {sli2 = append(sli2, sli2...)fmt.Printf("len=%d cap=%d\n", len(sli2), cap(sli2))}}
runtime/slice
type slice struct {array unsafe.Pointerlen intcap int
}func growslice(et *_type, old slice, cap int) slice {if raceenabled {callerpc := getcallerpc()racereadrangepc(old.array, uintptr(old.len*int(et.size)), callerpc, abi.FuncPCABIInternal(growslice))}if msanenabled {msanread(old.array, uintptr(old.len*int(et.size)))}if asanenabled {asanread(old.array, uintptr(old.len*int(et.size)))}if cap < old.cap {panic(errorString("growslice: cap out of range"))}if et.size == 0 {// append should not create a slice with nil pointer but non-zero len.// We assume that append doesn't need to preserve old.array in this case.return slice{unsafe.Pointer(&zerobase), old.len, cap}}newcap := old.capdoublecap := newcap + newcapif cap > doublecap {newcap = cap} else {const threshold = 256if old.cap < threshold {newcap = doublecap} else {// Check 0 < newcap to detect overflow// and prevent an infinite loop.for 0 < newcap && newcap < cap {// Transition from growing 2x for small slices// to growing 1.25x for large slices. This formula// gives a smooth-ish transition between the two.newcap += (newcap + 3*threshold) / 4}// Set newcap to the requested cap when// the newcap calculation overflowed.if newcap <= 0 {newcap = cap}}}