Delete Entries from a Slice While Iterating Over it in Go

As you have mentioned elsewhere, you can allocate new memory block and copy only valid elements to it. However, if you want to avoid the allocation, you can rewrite your slice in-place:

i := 0 // output index
for _, x := range s {
    if isValid(x) {
        // copy and increment index
        s[i] = x
        i++
    }
}
// Prevent memory leak by erasing truncated values 
// (not needed if values don't contain pointers, directly or indirectly)
for j := i; j < len(s); j++ {
    s[j] = nil
}
s = s[:i]

Full example: http://play.golang.org/p/FNDFswPeDJ

Note this will leave old values after index i in the underlying array, so this will leak memory until the slice itself is garbage collected, if values are or contain pointers. You can solve this by setting all values to nil or the zero value from i until the end of the slice before truncating it.


There might be better ways, but here's an example that deletes the even values from a slice:

m := []int{1,2,3,4,5,6}

deleted := 0
for i := range m {
    j := i - deleted
    if (m[j] & 1) == 0 {
        m = m[:j+copy(m[j:], m[j+1:])]
        deleted++
    } 
}

Note that I don't get the element using the i, d := range m syntax, since d would end up getting set to the wrong elements once you start deleting from the slice.


I know its answered long time ago but i use something like this in other languages, but i don't know if it is the golang way.

Just iterate from back to front so you don't have to worry about indexes that are deleted. I am using the same example as Adam.

m = []int{3, 7, 2, 9, 4, 5}

for i := len(m)-1; i >= 0; i-- {
    if m[i] < 5 {
        m = append(m[:i], m[i+1:]...)
    }
}

Tags:

Go