sneak-peek on golang’s array/slice allocation

Dealing with arrays is one of the most trivial however painstaking thing programmers needs to tackle. C/C++ fans have the choice of either fully containerized vectors + advanced data structures, or falling back the primal c pointer arrays. Go sort of absorbs both the c style pointer and the convenient container features modern languages like C++ provide. So in golang array is really dynamic like vectors, and along with array it derives out a “Slice” structure, providing convenient concat/slicing operations, but under the hood it’s no different handling pointers on a pre-allocated array space.

I recently work on projects that makes vast use of append() in Go, and what’s funny about this function is you’ll have to assign back the returned value of this function — which is a pointer to the new/old allocated array, back to the old array pointer, that is the array won’t grow in place. From this perspective Go’s low level nature really exposes — it’s pointer reference may really point to a heap allocation, it’s just shown to the user in a more transparent way. Since we’re really calling append a lot of times, we’d like to see how this allocation actually goes, here’s a sample code snippet on sneak-peeking the allocation of an empty integer array:

import (
“fmt”
)

func main() {
var a []int
for i := 0; i < 50; i++ {
a = append(a, 1)
fmt.Printf(“%p\n”, a)
fmt.Println(cap(a))
fmt.Println(len(a))
}

}

the output is shown as follow, apparently Go is allocating power of 2 exponentially as append() call grows. The cap() output indicate the actually array’s capacity, while len() is the slice length — the actually growth of the array as result of append(). Notice that we actually created a slice by using “[]int” with no size indicator in the bracket. As mentioned before, sometimes you really feel like Go is nothing but a thin decorator on C, except it gives you transparent info on what it’s doing under the hood, like enabling cap() and len() query, rather than in C++ containers where it’s hiding as much information as possible in the so-called object-oriented way.

0x10410020
2
1
0x10410020
2
2
0x10410050
4
3
0x10410050
4
4
0x10454000
8
5
0x10454000
8
6
0x10454000
8
7
0x10454000
8
8
0x10436080
16
9
0x10436080
16
10
0x10436080
16
11
0x10436080
16
12
0x10436080
16
13
0x10436080
16
14
0x10436080
16
15
0x10436080
16
16
0x10456000
32
17
0x10456000
32
18
0x10456000
32
19
0x10456000
32
20
0x10456000
32
21
0x10456000
32
22
0x10456000
32
23
0x10456000
32
24
0x10456000
32
25
0x10456000
32
26
0x10456000
32
27
0x10456000
32
28
0x10456000
32
29
0x10456000
32
30
0x10456000
32
31
0x10456000
32
32
0x10458000
64
33
0x10458000
64
34
0x10458000
64
35
0x10458000
64
36
0x10458000
64
37
0x10458000
64
38
0x10458000
64
39
0x10458000
64
40
0x10458000
64
41
0x10458000
64
42
0x10458000
64
43
0x10458000
64
44
0x10458000
64
45
0x10458000
64
46
0x10458000
64
47
0x10458000
64
48
0x10458000
64
49
0x10458000
64
50

Leave a comment