We know that Golang slices will be expanded when the capacity is insufficient. What is the principle of expansion? Is it doubled every time? Let’s combine the source code to tell you the answer.
1. Source code
Version : go1.15.6 src/runtime/
//go1.15.6 Source code src/runtime/func growslice(et *_type, old slice, cap int) slice { //Omit some judgment code //The calculation expansion part // Where, cap: the required capacity, newcap: the final applied capacity newcap := doublecap := newcap + newcap if cap > doublecap { newcap = cap } else { if < 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 } } } //Omit some judgment code}
II. Principle
1. If the current required capacity (cap) is greater than twice the original capacity (doublecap), the final applied capacity (newcap) is the current required capacity (cap);
2. If <condition 1> is not met, it means that the current required capacity (cap) is not greater than twice the original capacity (doublecap), then make the following judgment;
3. If the original slice length () is less than 1024, the final applied capacity (newcap) is equal to twice the original capacity (doublecap);
4. Otherwise, the final application capacity (newcap, the initial value is equal to ) will be increased by newcap/4 each time until it is greater than the required capacity (cap). Then, it is determined whether the final application capacity (newcap) overflows. If it is overflowed, the final application capacity (newcap) is equal to the required capacity (cap);
You may not understand this, let’s take a few examples:
2.1 Example 1
Verification condition 1:
package main import "fmt" func main() { //Example in Article 1: var slice = []int{1, 2, 3} var slice1 = []int{4, 5, 6, 7, 8, 9, 10, 11, 12} ("slice %v len = %v cap = %v\n", slice, len(slice), cap(slice)) ("slice1 %v len = %v cap = %v\n", slice1, len(slice1), cap(slice1)) slice = append(slice, slice1...) ("slice %v len = %v cap = %v\n", slice, len(slice), cap(slice)) }
Output:
[root@localhost test]# go run
slice [1 2 3] len = 3 cap = 3
slice1 [4 5 6 7 8 9 10 11 12] len = 9 cap = 9
slice [1 2 3 4 5 6 7 8 9 10 11 12] len = 12 cap = 12
[root@localhost test]#
In Example 1, the required capacity cap = 9+3 = 12, twice the original capacity doublecap = 2 * 3 = 6, satisfying <condition 1> that is, the required capacity is greater than twice the original capacity, so the final application capacity newcap = cap = 12.
2.2 Example 2
Verification Condition 2, 3:
package main import "fmt" func main() { //Examples in Articles 2 and 3: var slice = []int{1, 2, 3, 4, 5, 6, 7} var slice1 = []int{8, 9} ("slice %v len = %v cap = %v\n", slice, len(slice), cap(slice)) ("slice1 %v len = %v cap = %v\n", slice1, len(slice1), cap(slice1)) slice = append(slice, slice1...) ("slice %v len = %v cap = %v\n", slice, len(slice), cap(slice)) }
Output:
[root@localhost test]# go run
slice [1 2 3 4 5 6 7] len = 7 cap = 7
slice1 [8 9] len = 2 cap = 2
slice [1 2 3 4 5 6 7 8 9] len = 9 cap = 14
[root@localhost test]#
In Example 2, the required capacity cap = 7+2 = 9, twice the original capacity doublecap = 2*7 = 14, the original slice length = 7, and the <condition 2,3> is met, the required capacity is less than twice the original capacity, and the original slice length is less than 1024, so, the final application capacity newcap = doublecap = 14.
2.3 Example 3
Verification Condition 4:
package main import "fmt" func main() { //Example in Article 2: var slice []int for i := 0; i < 1024; i++ { slice = append(slice, i) } var slice1 = []int{1024, 1025} ("slice %v len = %v cap = %v\n", slice, len(slice), cap(slice)) ("slice1 %v len = %v cap = %v\n", slice1, len(slice1), cap(slice1)) slice = append(slice, slice1...) ("slice %v len = %v cap = %v\n", slice, len(slice), cap(slice)) }
Output:
[root@localhost test]# go run
slice [0 1 2 3 4 5 6……1017 1018 1019 1020 1021 1022 1023] len = 1024 cap = 1024
slice1 [1024 1025] len = 2 cap = 2
slice [0 1 2 3 4 5 6……1017 1018 1019 1020 1021 1022 1023 1024 1025] len = 1026 cap = 1280
[root@localhost test]#
In Example 3, the required capacity cap = 1024+2 = 1026, doublecap = 2048, = 1024, <condition 4> is satisfied, so, newcap = 1024 + 1024/4 = 1280.
This is the end of this article about the principle of Golang slice expansion mechanism. For more related contents of Golang slice expansion mechanism, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!