1. slice的結(jié)構(gòu)
type slice struct {
index *interface //指向首元素的指針
len int //長(zhǎng)度
cap int //容量
}
slice是值類型
slice類型聲明后類似于:
var arr slice
而非 var arr *slice
append時(shí),如果超過cap容量,會(huì)重新分配空間.
新空間的指針會(huì)被保存在index中,slice本身的指針不變.
舉個(gè)栗子??:
func F() {
intArr := make([]int, 1)
fmt.Println(&intArr[0], len(intArr), cap(intArr))
defer f(intArr)
intArr = append(intArr, 1)
fmt.Println(&intArr[0], len(intArr), cap(intArr))
return
}
func f(intArr []int) {
fmt.Println(&intArr[0], len(intArr), cap(intArr))
}
//結(jié)果
0xc42000d2d0 1 1
0xc42000d300 2 2
0xc42000d2d0 1 1
- 在defer中,保存了一個(gè)副本,拷貝了intArr的值,
在后面append中,因?yàn)槿萘?cap)不夠,給intArr的index重新分配了空間,
因?yàn)閐efer中保存的是intArr的值,所以defer打印出來的是原來的slice值
func F1() {
intArr := make([]int, 1)
fmt.Println(&intArr[0], len(intArr), cap(intArr))
defer f1(&intArr)
intArr = append(intArr, 1)
fmt.Println(&intArr[0], len(intArr), cap(intArr))
return
}
func f1(ia *[]int) {
intArr := *ia
fmt.Println(&intArr[0], len(intArr), cap(intArr))
}
//結(jié)果
0xc42000d2d0 1 1
0xc42000d300 2 2
0xc42000d300 2 2
- 在defer中,保存了一個(gè)副本,拷貝了intArr的指針,
在后面append中,因?yàn)槿萘?cap)不夠,給intArr的index重新分配了空間,
因?yàn)閐efer中保存的是intArr的指針,所以打印出來的是新的的slice值
2. slice的擴(kuò)容
func F() {
intArr := make([]int, 0, 0)
intArr = append(intArr, 1)
fmt.Println(&intArr[0], len(intArr), cap(intArr))
intArr = append(intArr, 2)
fmt.Println(&intArr[0], len(intArr), cap(intArr))
intArr = append(intArr, 3)
fmt.Println(&intArr[0], len(intArr), cap(intArr))
intArr = append(intArr, 4)
fmt.Println(&intArr[0], len(intArr), cap(intArr))
return
}
//結(jié)果
0xc42000d2d0 1 1
0xc42000d300 2 2
0xc4200cc660 3 4
0xc4200cc660 4 4
在對(duì)slice進(jìn)行append等操作時(shí)俗冻,可能會(huì)造成slice的自動(dòng)擴(kuò)容。其擴(kuò)容時(shí)的大小增長(zhǎng)規(guī)則是:
- 如果新的大小是當(dāng)前大小2倍以上,則大小增長(zhǎng)為新大小
- 否則循環(huán)以下操作:如果當(dāng)前大小小于1024,按每次2倍增長(zhǎng),否則每次按當(dāng)前大小1/4增長(zhǎng)。直到增長(zhǎng)的大小超過或等于新大小。