Append to slice

suggest change

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 pattern 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 it takes 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 of 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.

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:



Table Of Contents