Is it safe to remove selected keys from map within a range loop?

Everton picture Everton · Apr 22, 2014 · Viewed 43k times · Source

How can one remove selected keys from a map? Is it safe to combine delete() with range, as in the code below?

package main

import "fmt"

type Info struct {
    value string
}

func main() {
    table := make(map[string]*Info)

    for i := 0; i < 10; i++ {
        str := fmt.Sprintf("%v", i)
        table[str] = &Info{str}
    }

    for key, value := range table {
        fmt.Printf("deleting %v=>%v\n", key, value.value)
        delete(table, key)
    }
}

https://play.golang.org/p/u1vufvEjSw

Answer

Sebastian picture Sebastian · Apr 22, 2014

This is safe! You can also find a similar sample in Effective Go:

for key := range m {
    if key.expired() {
        delete(m, key)
    }
}

And the language specification:

The iteration order over maps is not specified and is not guaranteed to be the same from one iteration to the next. If map entries that have not yet been reached are removed during iteration, the corresponding iteration values will not be produced. If map entries are created during iteration, that entry may be produced during the iteration or may be skipped. The choice may vary for each entry created and from one iteration to the next. If the map is nil, the number of iterations is 0.