Essential Go Slices  Suggest an edit

Append to slice

Built-in function append(slice, elements...) adds element to a slice and returns a new slice.

Append a single value

a := []string{"hello"}
a = append(a, "world")
fmt.Printf("a: %#v\n", a)
a: []string{"hello", "world"}

Append multiple values

a := []string{"hello"}
a = append(a, "world", "now")
fmt.Printf("a: %#v\n", a)
a: []string{"hello", "world", "now"}

Append a slice to a slice

a := []string{"!"}
a2 := []string{"Hello", "world"}
a = append(a, a2...)
fmt.Printf("a: %#v\n", a)
a: []string{"!", "Hello", "world"}

Append might create a new slice

Maybe you noticed the patter a = append(a, ....).

A slice uses an array of fixed size for storage. When number of slice elements exceeds size of array, append needs to re-allocate the array and create a new slice. For efficiency the newly allocated array has some spare elements, so that we don't have to re-allocate backing array every time we append an element to a slice.

This program shows how many elements does it take to re-allocate new array.

var a []int
ptr := fmt.Sprintf("%p", a)
n := 0
nAppends := 0
for {
	a = append(a, 1)
	nAppends++
	currPtr := fmt.Sprintf("%p", a)
	if currPtr != ptr {
		fmt.Printf("Appends needed to re-allocate slice: %d\n", nAppends)
		nAppends = 0
		ptr = currPtr
		n++
		if n == 6 {
			break
		}
	}
}
Appends needed to re-allocate slice: 1
Appends needed to re-allocate slice: 1
Appends needed to re-allocate slice: 1
Appends needed to re-allocate slice: 2
Appends needed to re-allocate slice: 4
Appends needed to re-allocate slice: 8

As you can see, the number appends needed to re-create the array increases with the size of the slice.

Go doesn't allow comparing slices so we use the fact that in current implementation we can take address of the slice (%p) and that address can be used as identity of slice.

This is an internal implementation detail that might change in the future.

  ↑ ↓ to navigate     ↵ to select     Esc to close