Remove elements from slice

suggest change

We use []int in our examples but the code works for slices of all types.

Remove a single element at a given index

main.go

	s := []int{10, 11, 12, 13}

	i := 2 // index of 12
	s = append(s[:i], s[i+1:]...)

	fmt.Printf("s: %#v\n", s)

Output:

s: []int{10, 11, 13}

Remove multiple elements

main.go

	s := []int{10, 11, 12, 13}

	i := 1 // index of 11
	n := 2 // remove 2 elements

	s = append(s[:i], s[i+n:]...)

	fmt.Printf("s: %#v\n", s)

Output:

s: []int{10, 13}

Efficiency of removal

Note on efficiency: Go compiler is smart enough to re-use the space in the original slice, so this method is quite efficient. It doesn't allocate new space and merely copies the elements within the slice. We can verify this:

main.go

	s := []int{10, 11, 12, 13}
	fmt.Printf("&s[0]: %p, cap(s): %d\n", &s[0], cap(s))
	fmt.Printf("s: %#v\n", s)

	i := 1 // index of 11
	n := 2 // remove 2 elements

	s = append(s[:i], s[i+n:]...)

	fmt.Print("\nAfter removal:\n")
	fmt.Printf("&s[0]: %p, cap(s): %d\n", &s[0], cap(s))
	fmt.Printf("s: %#v\n", s)

	s = append(s, 1, 2, 3, 4)
	fmt.Printf("\nAfter appending beyond remaining capacity:\n")
	fmt.Printf("&s[0]: %p, cap(s): %d\n", &s[0], cap(s))
	fmt.Printf("s: %#v\n", s)

Output:

&s[0]: 0xc0000140a0, cap(s): 4
s: []int{10, 11, 12, 13}

After removal:
&s[0]: 0xc0000140a0, cap(s): 4
s: []int{10, 13}

After appending beyond remaining capacity:
&s[0]: 0xc000074000, cap(s): 8
s: []int{10, 13, 1, 2, 3, 4}

%p formatting directive prints the physical address in memory of a variable. We can verify that s points to the same physical memory and has the same capacity before and after removal, so the underlying array.

We can also see that appending 4 elements, which is beyond remaining capacity of 2, caused the array to be re-allocated.

Optimized, in-place removal

If we don't care to preserve the order of elements, we can optimize removal even further:

main.go

	s := []int{10, 11, 12, 13}

	i := 1 // index of 11
	lastIdx := len(s) - 1

	s[i] = s[lastIdx]
	s = s[:lastIdx]

	fmt.Printf("s: %#v\n", s)

Output:

s: []int{10, 13, 12}

We overwrite the element we want to remove with the last element in the slice and shrink the slice by 1.

This copies a single elements compared to copying all elements from i to end of slice. This doesn't matter in small slices but is much faster if you have slices with thousands of elements

Feedback about page:

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



Table Of Contents