Go语言中append()函数的扩容实验

在学习Go语言数组的append()函数时遇到一个有趣的现象,当我使用如下代码测试扩容的时候:

import "fmt"

func main() {
   var numbers []int
   printSlice(numbers)

   numbers = append(numbers, 0)
   printSlice(numbers)

   numbers = append(numbers, 1)
   printSlice(numbers)

   numbers = append(numbers, 2)
   printSlice(numbers)

   numbers = append(numbers, 3)
   printSlice(numbers)

   numbers = append(numbers, 4)
   printSlice(numbers)

   numbers = append(numbers, 5, 6, 7)
   printSlice(numbers)

   numbers = append(numbers, 8)
   printSlice(numbers)

   numbers = append(numbers, 9, 10, 11)
   printSlice(numbers)
}

func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

输出如下:

可以看到容量是以2倍的速率增长的,但是换一种测试方式:

package main

import "fmt"

func main() {
   var numbers []int
   printSlice(numbers)

   numbers = append(numbers, 0)
   printSlice(numbers)

   numbers = append(numbers, 1, 2, 3, 4)
   printSlice(numbers)

   numbers = append(numbers, 5)
   printSlice(numbers)

   numbers = append(numbers, 6)
   printSlice(numbers)
}

func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

输入如下:

结局似乎和预想的不太一样,第一次添加一个元素,扩容到了长度和容量都为1的情况,第二次一次性添加了四个元素,当按照二倍增长来推算的话首先cap要增长到2,发现不够后继续增长2倍到4,发现还是不够,继续增长到8,所以当我一次性添加四个元素的时候,本应该输出len=5 cap=8 slice=[0 1 2 3 4],但实际输出的cap是6,由此可知:

在Go语言中,通过append()函数向slice中添加元素,按照二倍增长后capacity依然不够用时,会将capacity设置为当前数组的length+1.


更正!!!

更新了实验,我有点摸不透了兄弟们...(向初始cap为0的空slice中一次性添加1个、2个、...、300个的实验代码和结果如下,大概看了一下扩容后cap的计算结果,还是有些规律的,不过具体的算法懒得梳理了,有感兴趣的大佬可以告知一下)

package main

import "fmt"

func printSliceBefore(x []int) {
	fmt.Printf("init len[%d] cap[%d] -> ", len(x), cap(x))
}

func printSliceAfter(x []int) {
	fmt.Printf("After append: len[%d] cap[%d]\n", len(x), cap(x))
}

func main() {
	for i := 1; i <= 300; i++ {
		var numbers = make([]int, 0)
		printSliceBefore(numbers)
		numbers = append(numbers, make([]int, i)...)
		printSliceAfter(numbers)
	}
}

=======================================================
[Running] go run "c:\Users\Hyleon\hello\hello.go"
init len[0] cap[0] -> After append: len[1] cap[1]
init len[0] cap[0] -> After append: len[2] cap[2]
init len[0] cap[0] -> After append: len[3] cap[3]
init len[0] cap[0] -> After append: len[4] cap[4]
init len[0] cap[0] -> After append: len[5] cap[6]
init len[0] cap[0] -> After append: len[6] cap[6]
init len[0] cap[0] -> After append: len[7] cap[8]
init len[0] cap[0] -> After append: len[8] cap[8]
init len[0] cap[0] -> After append: len[9] cap[10]
init len[0] cap[0] -> After append: len[10] cap[10]
init len[0] cap[0] -> After append: len[11] cap[12]
init len[0] cap[0] -> After append: len[12] cap[12]
init len[0] cap[0] -> After append: len[13] cap[14]
init len[0] cap[0] -> After append: len[14] cap[14]
init len[0] cap[0] -> After append: len[15] cap[16]
init len[0] cap[0] -> After append: len[16] cap[16]
init len[0] cap[0] -> After append: len[17] cap[18]
init len[0] cap[0] -> After append: len[18] cap[18]
init len[0] cap[0] -> After append: len[19] cap[20]
init len[0] cap[0] -> After append: len[20] cap[20]
init len[0] cap[0] -> After append: len[21] cap[22]
init len[0] cap[0] -> After append: len[22] cap[22]
init len[0] cap[0] -> After append: len[23] cap[24]
init len[0] cap[0] -> After append: len[24] cap[24]
init len[0] cap[0] -> After append: len[25] cap[26]
init len[0] cap[0] -> After append: len[26] cap[26]
init len[0] cap[0] -> After append: len[27] cap[28]
init len[0] cap[0] -> After append: len[28] cap[28]
init len[0] cap[0] -> After append: len[29] cap[30]
init len[0] cap[0] -> After append: len[30] cap[30]
init len[0] cap[0] -> After append: len[31] cap[32]
init len[0] cap[0] -> After append: len[32] cap[32]
init len[0] cap[0] -> After append: len[33] cap[36]
init len[0] cap[0] -> After append: len[34] cap[36]
init len[0] cap[0] -> After append: len[35] cap[36]
init len[0] cap[0] -> After append: len[36] cap[36]
init len[0] cap[0] -> After append: len[37] cap[40]
init len[0] cap[0] -> After append: len[38] cap[40]
init len[0] cap[0] -> After append: len[39] cap[40]
init len[0] cap[0] -> After append: len[40] cap[40]
init len[0] cap[0] -> After append: len[41] cap[44]
init len[0] cap[0] -> After append: len[42] cap[44]
init len[0] cap[0] -> After append: len[43] cap[44]
init len[0] cap[0] -> After append: len[44] cap[44]
init len[0] cap[0] -> After append: len[45] cap[48]
init len[0] cap[0] -> After append: len[46] cap[48]
init len[0] cap[0] -> After append: len[47] cap[48]
init len[0] cap[0] -> After append: len[48] cap[48]
init len[0] cap[0] -> After append: len[49] cap[52]
init len[0] cap[0] -> After append: len[50] cap[52]
init len[0] cap[0] -> After append: len[51] cap[52]
init len[0] cap[0] -> After append: len[52] cap[52]
init len[0] cap[0] -> After append: len[53] cap[56]
init len[0] cap[0] -> After append: len[54] cap[56]
init len[0] cap[0] -> After append: len[55] cap[56]
init len[0] cap[0] -> After append: len[56] cap[56]
init len[0] cap[0] -> After append: len[57] cap[60]
init len[0] cap[0] -> After append: len[58] cap[60]
init len[0] cap[0] -> After append: len[59] cap[60]
init len[0] cap[0] -> After append: len[60] cap[60]
init len[0] cap[0] -> After append: len[61] cap[64]
init len[0] cap[0] -> After append: len[62] cap[64]
init len[0] cap[0] -> After append: len[63] cap[64]
init len[0] cap[0] -> After append: len[64] cap[64]
init len[0] cap[0] -> After append: len[65] cap[72]
init len[0] cap[0] -> After append: len[66] cap[72]
init len[0] cap[0] -> After append: len[67] cap[72]
init len[0] cap[0] -> After append: len[68] cap[72]
init len[0] cap[0] -> After append: len[69] cap[72]
init len[0] cap[0] -> After append: len[70] cap[72]
init len[0] cap[0] -> After append: len[71] cap[72]
init len[0] cap[0] -> After append: len[72] cap[72]
init len[0] cap[0] -> After append: len[73] cap[80]
init len[0] cap[0] -> After append: len[74] cap[80]
init len[0] cap[0] -> After append: len[75] cap[80]
init len[0] cap[0] -> After append: len[76] cap[80]
init len[0] cap[0] -> After append: len[77] cap[80]
init len[0] cap[0] -> After append: len[78] cap[80]
init len[0] cap[0] -> After append: len[79] cap[80]
init len[0] cap[0] -> After append: len[80] cap[80]
init len[0] cap[0] -> After append: len[81] cap[88]
init len[0] cap[0] -> After append: len[82] cap[88]
init len[0] cap[0] -> After append: len[83] cap[88]
init len[0] cap[0] -> After append: len[84] cap[88]
init len[0] cap[0] -> After append: len[85] cap[88]
init len[0] cap[0] -> After append: len[86] cap[88]
init len[0] cap[0] -> After append: len[87] cap[88]
init len[0] cap[0] -> After append: len[88] cap[88]
init len[0] cap[0] -> After append: len[89] cap[96]
init len[0] cap[0] -> After append: len[90] cap[96]
init len[0] cap[0] -> After append: len[91] cap[96]
init len[0] cap[0] -> After append: len[92] cap[96]
init len[0] cap[0] -> After append: len[93] cap[96]
init len[0] cap[0] -> After append: len[94] cap[96]
init len[0] cap[0] -> After append: len[95] cap[96]
init len[0] cap[0] -> After append: len[96] cap[96]
init len[0] cap[0] -> After append: len[97] cap[112]
init len[0] cap[0] -> After append: len[98] cap[112]
init len[0] cap[0] -> After append: len[99] cap[112]
init len[0] cap[0] -> After append: len[100] cap[112]
init len[0] cap[0] -> After append: len[101] cap[112]
init len[0] cap[0] -> After append: len[102] cap[112]
init len[0] cap[0] -> After append: len[103] cap[112]
init len[0] cap[0] -> After append: len[104] cap[112]
init len[0] cap[0] -> After append: len[105] cap[112]
init len[0] cap[0] -> After append: len[106] cap[112]
init len[0] cap[0] -> After append: len[107] cap[112]
init len[0] cap[0] -> After append: len[108] cap[112]
init len[0] cap[0] -> After append: len[109] cap[112]
init len[0] cap[0] -> After append: len[110] cap[112]
init len[0] cap[0] -> After append: len[111] cap[112]
init len[0] cap[0] -> After append: len[112] cap[112]
init len[0] cap[0] -> After append: len[113] cap[128]
init len[0] cap[0] -> After append: len[114] cap[128]
init len[0] cap[0] -> After append: len[115] cap[128]
init len[0] cap[0] -> After append: len[116] cap[128]
init len[0] cap[0] -> After append: len[117] cap[128]
init len[0] cap[0] -> After append: len[118] cap[128]
init len[0] cap[0] -> After append: len[119] cap[128]
init len[0] cap[0] -> After append: len[120] cap[128]
init len[0] cap[0] -> After append: len[121] cap[128]
init len[0] cap[0] -> After append: len[122] cap[128]
init len[0] cap[0] -> After append: len[123] cap[128]
init len[0] cap[0] -> After append: len[124] cap[128]
init len[0] cap[0] -> After append: len[125] cap[128]
init len[0] cap[0] -> After append: len[126] cap[128]
init len[0] cap[0] -> After append: len[127] cap[128]
init len[0] cap[0] -> After append: len[128] cap[128]
init len[0] cap[0] -> After append: len[129] cap[144]
init len[0] cap[0] -> After append: len[130] cap[144]
init len[0] cap[0] -> After append: len[131] cap[144]
init len[0] cap[0] -> After append: len[132] cap[144]
init len[0] cap[0] -> After append: len[133] cap[144]
init len[0] cap[0] -> After append: len[134] cap[144]
init len[0] cap[0] -> After append: len[135] cap[144]
init len[0] cap[0] -> After append: len[136] cap[144]
init len[0] cap[0] -> After append: len[137] cap[144]
init len[0] cap[0] -> After append: len[138] cap[144]
init len[0] cap[0] -> After append: len[139] cap[144]
init len[0] cap[0] -> After append: len[140] cap[144]
init len[0] cap[0] -> After append: len[141] cap[144]
init len[0] cap[0] -> After append: len[142] cap[144]
init len[0] cap[0] -> After append: len[143] cap[144]
init len[0] cap[0] -> After append: len[144] cap[144]
init len[0] cap[0] -> After append: len[145] cap[160]
init len[0] cap[0] -> After append: len[146] cap[160]
init len[0] cap[0] -> After append: len[147] cap[160]
init len[0] cap[0] -> After append: len[148] cap[160]
init len[0] cap[0] -> After append: len[149] cap[160]
init len[0] cap[0] -> After append: len[150] cap[160]
init len[0] cap[0] -> After append: len[151] cap[160]
init len[0] cap[0] -> After append: len[152] cap[160]
init len[0] cap[0] -> After append: len[153] cap[160]
init len[0] cap[0] -> After append: len[154] cap[160]
init len[0] cap[0] -> After append: len[155] cap[160]
init len[0] cap[0] -> After append: len[156] cap[160]
init len[0] cap[0] -> After append: len[157] cap[160]
init len[0] cap[0] -> After append: len[158] cap[160]
init len[0] cap[0] -> After append: len[159] cap[160]
init len[0] cap[0] -> After append: len[160] cap[160]
init len[0] cap[0] -> After append: len[161] cap[176]
init len[0] cap[0] -> After append: len[162] cap[176]
init len[0] cap[0] -> After append: len[163] cap[176]
init len[0] cap[0] -> After append: len[164] cap[176]
init len[0] cap[0] -> After append: len[165] cap[176]
init len[0] cap[0] -> After append: len[166] cap[176]
init len[0] cap[0] -> After append: len[167] cap[176]
init len[0] cap[0] -> After append: len[168] cap[176]
init len[0] cap[0] -> After append: len[169] cap[176]
init len[0] cap[0] -> After append: len[170] cap[176]
init len[0] cap[0] -> After append: len[171] cap[176]
init len[0] cap[0] -> After append: len[172] cap[176]
init len[0] cap[0] -> After append: len[173] cap[176]
init len[0] cap[0] -> After append: len[174] cap[176]
init len[0] cap[0] -> After append: len[175] cap[176]
init len[0] cap[0] -> After append: len[176] cap[176]
init len[0] cap[0] -> After append: len[177] cap[192]
init len[0] cap[0] -> After append: len[178] cap[192]
init len[0] cap[0] -> After append: len[179] cap[192]
init len[0] cap[0] -> After append: len[180] cap[192]
init len[0] cap[0] -> After append: len[181] cap[192]
init len[0] cap[0] -> After append: len[182] cap[192]
init len[0] cap[0] -> After append: len[183] cap[192]
init len[0] cap[0] -> After append: len[184] cap[192]
init len[0] cap[0] -> After append: len[185] cap[192]
init len[0] cap[0] -> After append: len[186] cap[192]
init len[0] cap[0] -> After append: len[187] cap[192]
init len[0] cap[0] -> After append: len[188] cap[192]
init len[0] cap[0] -> After append: len[189] cap[192]
init len[0] cap[0] -> After append: len[190] cap[192]
init len[0] cap[0] -> After append: len[191] cap[192]
init len[0] cap[0] -> After append: len[192] cap[192]
init len[0] cap[0] -> After append: len[193] cap[224]
init len[0] cap[0] -> After append: len[194] cap[224]
init len[0] cap[0] -> After append: len[195] cap[224]
init len[0] cap[0] -> After append: len[196] cap[224]
init len[0] cap[0] -> After append: len[197] cap[224]
init len[0] cap[0] -> After append: len[198] cap[224]
init len[0] cap[0] -> After append: len[199] cap[224]
init len[0] cap[0] -> After append: len[200] cap[224]
init len[0] cap[0] -> After append: len[201] cap[224]
init len[0] cap[0] -> After append: len[202] cap[224]
init len[0] cap[0] -> After append: len[203] cap[224]
init len[0] cap[0] -> After append: len[204] cap[224]
init len[0] cap[0] -> After append: len[205] cap[224]
init len[0] cap[0] -> After append: len[206] cap[224]
init len[0] cap[0] -> After append: len[207] cap[224]
init len[0] cap[0] -> After append: len[208] cap[224]
init len[0] cap[0] -> After append: len[209] cap[224]
init len[0] cap[0] -> After append: len[210] cap[224]
init len[0] cap[0] -> After append: len[211] cap[224]
init len[0] cap[0] -> After append: len[212] cap[224]
init len[0] cap[0] -> After append: len[213] cap[224]
init len[0] cap[0] -> After append: len[214] cap[224]
init len[0] cap[0] -> After append: len[215] cap[224]
init len[0] cap[0] -> After append: len[216] cap[224]
init len[0] cap[0] -> After append: len[217] cap[224]
init len[0] cap[0] -> After append: len[218] cap[224]
init len[0] cap[0] -> After append: len[219] cap[224]
init len[0] cap[0] -> After append: len[220] cap[224]
init len[0] cap[0] -> After append: len[221] cap[224]
init len[0] cap[0] -> After append: len[222] cap[224]
init len[0] cap[0] -> After append: len[223] cap[224]
init len[0] cap[0] -> After append: len[224] cap[224]
init len[0] cap[0] -> After append: len[225] cap[256]
init len[0] cap[0] -> After append: len[226] cap[256]
init len[0] cap[0] -> After append: len[227] cap[256]
init len[0] cap[0] -> After append: len[228] cap[256]
init len[0] cap[0] -> After append: len[229] cap[256]
init len[0] cap[0] -> After append: len[230] cap[256]
init len[0] cap[0] -> After append: len[231] cap[256]
init len[0] cap[0] -> After append: len[232] cap[256]
init len[0] cap[0] -> After append: len[233] cap[256]
init len[0] cap[0] -> After append: len[234] cap[256]
init len[0] cap[0] -> After append: len[235] cap[256]
init len[0] cap[0] -> After append: len[236] cap[256]
init len[0] cap[0] -> After append: len[237] cap[256]
init len[0] cap[0] -> After append: len[238] cap[256]
init len[0] cap[0] -> After append: len[239] cap[256]
init len[0] cap[0] -> After append: len[240] cap[256]
init len[0] cap[0] -> After append: len[241] cap[256]
init len[0] cap[0] -> After append: len[242] cap[256]
init len[0] cap[0] -> After append: len[243] cap[256]
init len[0] cap[0] -> After append: len[244] cap[256]
init len[0] cap[0] -> After append: len[245] cap[256]
init len[0] cap[0] -> After append: len[246] cap[256]
init len[0] cap[0] -> After append: len[247] cap[256]
init len[0] cap[0] -> After append: len[248] cap[256]
init len[0] cap[0] -> After append: len[249] cap[256]
init len[0] cap[0] -> After append: len[250] cap[256]
init len[0] cap[0] -> After append: len[251] cap[256]
init len[0] cap[0] -> After append: len[252] cap[256]
init len[0] cap[0] -> After append: len[253] cap[256]
init len[0] cap[0] -> After append: len[254] cap[256]
init len[0] cap[0] -> After append: len[255] cap[256]
init len[0] cap[0] -> After append: len[256] cap[256]
init len[0] cap[0] -> After append: len[257] cap[288]
init len[0] cap[0] -> After append: len[258] cap[288]
init len[0] cap[0] -> After append: len[259] cap[288]
init len[0] cap[0] -> After append: len[260] cap[288]
init len[0] cap[0] -> After append: len[261] cap[288]
init len[0] cap[0] -> After append: len[262] cap[288]
init len[0] cap[0] -> After append: len[263] cap[288]
init len[0] cap[0] -> After append: len[264] cap[288]
init len[0] cap[0] -> After append: len[265] cap[288]
init len[0] cap[0] -> After append: len[266] cap[288]
init len[0] cap[0] -> After append: len[267] cap[288]
init len[0] cap[0] -> After append: len[268] cap[288]
init len[0] cap[0] -> After append: len[269] cap[288]
init len[0] cap[0] -> After append: len[270] cap[288]
init len[0] cap[0] -> After append: len[271] cap[288]
init len[0] cap[0] -> After append: len[272] cap[288]
init len[0] cap[0] -> After append: len[273] cap[288]
init len[0] cap[0] -> After append: len[274] cap[288]
init len[0] cap[0] -> After append: len[275] cap[288]
init len[0] cap[0] -> After append: len[276] cap[288]
init len[0] cap[0] -> After append: len[277] cap[288]
init len[0] cap[0] -> After append: len[278] cap[288]
init len[0] cap[0] -> After append: len[279] cap[288]
init len[0] cap[0] -> After append: len[280] cap[288]
init len[0] cap[0] -> After append: len[281] cap[288]
init len[0] cap[0] -> After append: len[282] cap[288]
init len[0] cap[0] -> After append: len[283] cap[288]
init len[0] cap[0] -> After append: len[284] cap[288]
init len[0] cap[0] -> After append: len[285] cap[288]
init len[0] cap[0] -> After append: len[286] cap[288]
init len[0] cap[0] -> After append: len[287] cap[288]
init len[0] cap[0] -> After append: len[288] cap[288]
init len[0] cap[0] -> After append: len[289] cap[336]
init len[0] cap[0] -> After append: len[290] cap[336]
init len[0] cap[0] -> After append: len[291] cap[336]
init len[0] cap[0] -> After append: len[292] cap[336]
init len[0] cap[0] -> After append: len[293] cap[336]
init len[0] cap[0] -> After append: len[294] cap[336]
init len[0] cap[0] -> After append: len[295] cap[336]
init len[0] cap[0] -> After append: len[296] cap[336]
init len[0] cap[0] -> After append: len[297] cap[336]
init len[0] cap[0] -> After append: len[298] cap[336]
init len[0] cap[0] -> After append: len[299] cap[336]
init len[0] cap[0] -> After append: len[300] cap[336]

[Done] exited with code=0 in 0.655 seconds

如果设定初始cap为10,实验结果在开始时略微不同,后面的变化规律与前面的实验一致,所以仅设置循环40次

package main

import "fmt"

func printSliceBefore(x []int) {
	fmt.Printf("init len[%d] cap[%d] -> ", len(x), cap(x))
}

func printSliceAfter(x []int) {
	fmt.Printf("After append: len[%d] cap[%d]\n", len(x), cap(x))
}

func main() {
	for i := 1; i <= 40; i++ {
		var numbers = make([]int, 0, 10)
		printSliceBefore(numbers)
		numbers = append(numbers, make([]int, i)...)
		printSliceAfter(numbers)
	}
}

==========================================================
[Running] go run "c:\Users\Hyleon\hello\hello.go"
init len[0] cap[10] -> After append: len[1] cap[10]
init len[0] cap[10] -> After append: len[2] cap[10]
init len[0] cap[10] -> After append: len[3] cap[10]
init len[0] cap[10] -> After append: len[4] cap[10]
init len[0] cap[10] -> After append: len[5] cap[10]
init len[0] cap[10] -> After append: len[6] cap[10]
init len[0] cap[10] -> After append: len[7] cap[10]
init len[0] cap[10] -> After append: len[8] cap[10]
init len[0] cap[10] -> After append: len[9] cap[10]
init len[0] cap[10] -> After append: len[10] cap[10]
init len[0] cap[10] -> After append: len[11] cap[20]
init len[0] cap[10] -> After append: len[12] cap[20]
init len[0] cap[10] -> After append: len[13] cap[20]
init len[0] cap[10] -> After append: len[14] cap[20]
init len[0] cap[10] -> After append: len[15] cap[20]
init len[0] cap[10] -> After append: len[16] cap[20]
init len[0] cap[10] -> After append: len[17] cap[20]
init len[0] cap[10] -> After append: len[18] cap[20]
init len[0] cap[10] -> After append: len[19] cap[20]
init len[0] cap[10] -> After append: len[20] cap[20]
init len[0] cap[10] -> After append: len[21] cap[22]
init len[0] cap[10] -> After append: len[22] cap[22]
init len[0] cap[10] -> After append: len[23] cap[24]
init len[0] cap[10] -> After append: len[24] cap[24]
init len[0] cap[10] -> After append: len[25] cap[26]
init len[0] cap[10] -> After append: len[26] cap[26]
init len[0] cap[10] -> After append: len[27] cap[28]
init len[0] cap[10] -> After append: len[28] cap[28]
init len[0] cap[10] -> After append: len[29] cap[30]
init len[0] cap[10] -> After append: len[30] cap[30]
init len[0] cap[10] -> After append: len[31] cap[32]
init len[0] cap[10] -> After append: len[32] cap[32]
init len[0] cap[10] -> After append: len[33] cap[36]
init len[0] cap[10] -> After append: len[34] cap[36]
init len[0] cap[10] -> After append: len[35] cap[36]
init len[0] cap[10] -> After append: len[36] cap[36]
init len[0] cap[10] -> After append: len[37] cap[40]
init len[0] cap[10] -> After append: len[38] cap[40]
init len[0] cap[10] -> After append: len[39] cap[40]
init len[0] cap[10] -> After append: len[40] cap[40]

[Done] exited with code=0 in 0.644 seconds

扩容算法代码如下:

// growslice handles slice growth during append.
// It is passed the slice element type, the old slice, and the desired new minimum capacity,
// and it returns a new slice with at least that capacity, with the old data
// copied into it.
// The new slice's length is set to the old slice's length,
// NOT to the new requested capacity.
// This is for codegen convenience. The old slice's length is used immediately
// to calculate where to write new values during an append.
// TODO: When the old backend is gone, reconsider this decision.
// The SSA backend might prefer the new length or to return only ptr/cap and save stack space.
func growslice(et *_type, old slice, cap int) slice {
	if raceenabled {
		callerpc := getcallerpc()
		racereadrangepc(old.array, uintptr(old.len*int(et.size)), callerpc, funcPC(growslice))
	}
	if msanenabled {
		msanread(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.cap
	doublecap := newcap + newcap
	if cap > doublecap {
		newcap = cap
	} else {
		if old.cap < 1024 {
			newcap = doublecap
		} else {
			// Check 0 < newcap to detect overflow
			// and prevent an infinite loop.
			for 0 < newcap && newcap < cap {
				newcap += newcap / 4
			}
			// Set newcap to the requested cap when
			// the newcap calculation overflowed.
			if newcap <= 0 {
				newcap = cap
			}
		}
	}

	var overflow bool
	var lenmem, newlenmem, capmem uintptr
	// Specialize for common values of et.size.
	// For 1 we don't need any division/multiplication.
	// For sys.PtrSize, compiler will optimize division/multiplication into a shift by a constant.
	// For powers of 2, use a variable shift.
	switch {
	case et.size == 1:
		lenmem = uintptr(old.len)
		newlenmem = uintptr(cap)
		capmem = roundupsize(uintptr(newcap))
		overflow = uintptr(newcap) > maxAlloc
		newcap = int(capmem)
	case et.size == sys.PtrSize:
		lenmem = uintptr(old.len) * sys.PtrSize
		newlenmem = uintptr(cap) * sys.PtrSize
		capmem = roundupsize(uintptr(newcap) * sys.PtrSize)
		overflow = uintptr(newcap) > maxAlloc/sys.PtrSize
		newcap = int(capmem / sys.PtrSize)
	case isPowerOfTwo(et.size):
		var shift uintptr
		if sys.PtrSize == 8 {
			// Mask shift for better code generation.
			shift = uintptr(sys.Ctz64(uint64(et.size))) & 63
		} else {
			shift = uintptr(sys.Ctz32(uint32(et.size))) & 31
		}
		lenmem = uintptr(old.len) << shift
		newlenmem = uintptr(cap) << shift
		capmem = roundupsize(uintptr(newcap) << shift)
		overflow = uintptr(newcap) > (maxAlloc >> shift)
		newcap = int(capmem >> shift)
	default:
		lenmem = uintptr(old.len) * et.size
		newlenmem = uintptr(cap) * et.size
		capmem, overflow = math.MulUintptr(et.size, uintptr(newcap))
		capmem = roundupsize(capmem)
		newcap = int(capmem / et.size)
	}

	// The check of overflow in addition to capmem > maxAlloc is needed
	// to prevent an overflow which can be used to trigger a segfault
	// on 32bit architectures with this example program:
	//
	// type T [1<<27 + 1]int64
	//
	// var d T
	// var s []T
	//
	// func main() {
	//   s = append(s, d, d, d, d)
	//   print(len(s), "\n")
	// }
	if overflow || capmem > maxAlloc {
		panic(errorString("growslice: cap out of range"))
	}

	var p unsafe.Pointer
	if et.ptrdata == 0 {
		p = mallocgc(capmem, nil, false)
		// The append() that calls growslice is going to overwrite from old.len to cap (which will be the new length).
		// Only clear the part that will not be overwritten.
		memclrNoHeapPointers(add(p, newlenmem), capmem-newlenmem)
	} else {
		// Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory.
		p = mallocgc(capmem, et, true)
		if lenmem > 0 && writeBarrier.enabled {
			// Only shade the pointers in old.array since we know the destination slice p
			// only contains nil pointers because it has been cleared during alloc.
			bulkBarrierPreWriteSrcOnly(uintptr(p), uintptr(old.array), lenmem-et.size+et.ptrdata)
		}
	}
	memmove(p, old.array, lenmem)

	return slice{p, old.len, newcap}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值