Slice expansion strategy? How to expand capacity?
Capacity expansion strategy: If the capacity of the slice is less than 1024 elements, the capacity will be doubled when expanding. The total capacity doubled from 1 original to 2 current.
Once the number of elements exceeds 1024 elements, the growth factor becomes 1.25, which means that one-quarter of the original capacity is added each time.
Note: The capacity expanded is based on the original capacity, not the length of the original array.
Take an example of a scaling strategy:
func main() { slice := []int{10, 20, 30, 40} newSlice := append(slice, 50) ("Before slice = %v, Pointer = %p, len = %d, cap = %d\n", slice, &slice, len(slice), cap(slice)) ("Before newSlice = %v, Pointer = %p, len = %d, cap = %d\n", newSlice, &newSlice, len(newSlice), cap(newSlice)) newSlice[1] += 10 ("After slice = %v, Pointer = %p, len = %d, cap = %d\n", slice, &slice, len(slice), cap(slice)) ("After newSlice = %v, Pointer = %p, len = %d, cap = %d\n", newSlice, &newSlice, len(newSlice), cap(newSlice)) } // result Before slice = [10 20 30 40], Pointer = 0xc4200b0140, len = 4, cap = 4 Before newSlice = [10 20 30 40 50], Pointer = 0xc4200b0180, len = 5, cap = 8 After slice = [10 20 30 40], Pointer = 0xc4200b0140, len = 4, cap = 4 // The added numbers are added on the new sliceAfter newSlice = [10 30 30 40 50], Pointer = 0xc4200b0180, len = 5, cap = 8
From the results, we can see that the new slice is different from the previous slice, because the new slice changes a value and does not affect the original array. The array pointed to by the new slice is a brand new array, and the cap capacity has also changed.
So is it a new array or an old array?
Will the array be new after expansion? There are actually two situations.
The first case:
func main() { array := [4]int{10, 20, 30, 40} slice := array[0:2] newSlice := append(slice, 50) ("Before slice = %v, Pointer = %p, len = %d, cap = %d\n", slice, &slice, len(slice), cap(slice)) ("Before newSlice = %v, Pointer = %p, len = %d, cap = %d\n", newSlice, &newSlice, len(newSlice), cap(newSlice)) newSlice[1] += 10 ("After slice = %v, Pointer = %p, len = %d, cap = %d\n", slice, &slice, len(slice), cap(slice)) ("After newSlice = %v, Pointer = %p, len = %d, cap = %d\n", newSlice, &newSlice, len(newSlice), cap(newSlice)) ("After array = %v\n", array) } // result Before slice = [10 20], Pointer = 0xc4200c0040, len = 2, cap = 4 Before newSlice = [10 20 50], Pointer = 0xc4200c0060, len = 3, cap = 4 After slice = [10 30], Pointer = 0xc4200c0040, len = 2, cap = 4 After newSlice = [10 30 50], Pointer = 0xc4200c0060, len = 3, cap = 4 After array = [10 30 50 40]
From this result, it can be clearly seen that modifying the value of the new slice actually affects the value of the old slice. After the expansion, no new array was created, and the append operation also changed the value of the original array. If there are multiple slices on the original array, then these slices will affect and create an inexplicable bug!
This situation is also very likely to occur when literals create slices. When the third parameter cap passes the value, if the slice is created with literals, cap does not equal the total capacity pointing to the array, then this situation will happen.
Note: It is recommended that when creating slices with literals, the value of the cap must be kept awake to avoid bugs caused by sharing the original array.
The second case:
The second case is an example of a scaling strategy. After scaling, a new slice is generated because the capacity of the original array reaches its maximum value. If the capacity is expanded, a new piece of memory will be opened, and the original value will be copied over. After performing subsequent operations, it will not affect the original array.
Summary: Always keep the cap awake, and it is recommended to use the expansion strategy in the second case.
This is the end of this article about the detailed explanation of Go's slice expansion mechanism. For more related Go's slice expansion content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!