Go

How do you delete elements from a slice efficiently, and what changed with slices.Delete in Go 1.22?

Question 50MediumGo 1.22 to 1.25

There are three common patterns:

  • Order-preserving delete: O(n), using append or copy.
  • Unordered delete: O(1), swap with the last element.
  • In-place filter: O(n), no allocation.
// Order-preserving
s = append(s[:i], s[i+1:]...)       // or s = slices.Delete(s, i, i+1)

// O(1) unordered
s[i] = s[len(s)-1]
s = s[:len(s)-1]

// In-place filter, reusing the backing array
func filter[T any](s []T, keep func(T) bool) []T {
	out := s[:0]
	for _, v := range s {
		if keep(v) {
			out = append(out, v)
		}
	}
	clear(s[len(out):]) // zero the tail so the GC can free pointers
	return out
}
// Library equivalent: s = slices.DeleteFunc(s, func(v T) bool { return !keep(v) })

Go 1.22 change: slices.Delete, DeleteFunc, Compact, CompactFunc and Replace now zero the obsolete tail elements between the new len and the old len. This fixes the pointer-retention leak. It also breaks code that kept the old slice header and read those elements. They are now zero values, not stale data. Always use the returned slice: s = slices.Delete(s, i, j).

append(s[:i], s[i+1:]...) has the same aliasing issue. It changes the shared array, so any other slice over it sees shifted data.

More on Arrays, Slices, Maps & Strings

All 37 Arrays, Slices, Maps & Strings questions