deleting from a map

3,538 views
Skip to first unread message

Nathan Trimble

unread,
Mar 29, 2012, 2:55:50 PM3/29/12
to golang-nuts
Looking at Effective Go, I see the following example:

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

Is it safe to delete from m while iterating through it? That's always
been a big no-no in one of the languages (C#) I'm coming from.
Usually this means I need to create a temporary list of items to
remove and then remove them in another loop. If I don't need to do
that anymore that is great news.

BTW, congrats on Go1, and thanks for the great language :).

-Nate

Peter Bourgon

unread,
Mar 29, 2012, 3:02:54 PM3/29/12
to Nathan Trimble, golang-nuts
On Thu, Mar 29, 2012 at 8:55 PM, Nathan Trimble
<nathan....@gmail.com> wrote:
> Looking at Effective Go, I see the following example:
>
> for key := range m {
>    if expired(key) {
>        delete(m, key)
>    }
> }
>
> Is it safe to delete from m while iterating through it?

My understanding is "yes".

From http://golang.org/ref/spec#For_statements --

"The range expression is evaluated once before beginning the loop . .
. If map entries that have not yet been reached are deleted during
iteration, the corresponding iteration values will not be produced."

Evan Shaw

unread,
Mar 29, 2012, 3:02:51 PM3/29/12
to Nathan Trimble, golang-nuts
Yes, deleting while iterating is safe. The spec says: "If map entries

that have not yet been reached are deleted during iteration, the
corresponding iteration values will not be produced."

- Evan

Kyle Lemons

unread,
Mar 29, 2012, 3:03:13 PM3/29/12
to Nathan Trimble, golang-nuts
From my reading of the spec, it is safe:

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 deleted during iteration, the corresponding iteration values will not be produced. If map entries are inserted during iteration, the behavior is implementation-dependent, but the iteration values for each entry will be produced at most once. If the map is nil, the number of iterations is 0.

Jan Mercl

unread,
Mar 29, 2012, 3:06:25 PM3/29/12
to golan...@googlegroups.com
On Thursday, March 29, 2012 8:55:50 PM UTC+2, Nate Trimble wrote:
> Looking at Effective Go, I see the following example:
>
> for key := range m {
>     if expired(key) {
>     delete(m, key)
>     }
> }
>
> Is it safe to delete from m while iterating through it? That's always
> been a big no-no in one of the languages (C#) I'm coming from.
> Usually this means I need to create a temporary list of items to
> remove and then remove them in another loop. If I don't need to do
> that anymore that is great news.

Yes, it's safe: http://weekly.golang.org/ref/spec#For_statements

3. 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 deleted during iteration, the corresponding iteration values will not be produced. If map entries are inserted during iteration, the behavior is implementation-dependent, but the iteration values for each entry will be produced at most once. If the map is nil, the number of iterations is 0.

Nathan Trimble

unread,
Mar 29, 2012, 3:19:31 PM3/29/12
to golang-nuts
Thanks to all for the quick and informative responses. I really like
that this is part of the spec.

-Nate

Jonathan Amsterdam

unread,
Mar 29, 2012, 9:33:28 PM3/29/12
to golang-nuts
> If map entries that have not
> yet been reached are deleted during iteration, the corresponding iteration
> values will not be produced.

This is not the case exhibited by the OP's code, which again is

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

Note that the entry being deleted *has* been reached during the
iteration.

Not saying it's not safe, just saying that you can't tell from the
spec.

roger peppe

unread,
Mar 30, 2012, 3:26:24 AM3/30/12
to Jonathan Amsterdam, golang-nuts

given that the spec doesn't say that deleting from the map during
iteration is unsafe (and in fact explicitly mentions a case to
do with deleting when iterating), it *is* necessarily a safe operation.

"The built-in function delete removes the element with key k from a map m."

no caveats.

Norbert Roos

unread,
Mar 30, 2012, 5:08:40 AM3/30/12
to golan...@googlegroups.com
On 03/29/2012 09:06 PM, Jan Mercl wrote:

Is it thread-safe, too? When one go routine is iterating over the map,
and another one is deleting from it?

Norbert

Jan Mercl

unread,
Mar 30, 2012, 5:15:52 AM3/30/12
to golan...@googlegroups.com
On Friday, March 30, 2012 11:08:40 AM UTC+2, Norbert Roos wrote:

Is it thread-safe, too? When one go routine is iterating over the map,
and another one is deleting from it?

No, it isn't. 

Evan Shaw

unread,
Mar 30, 2012, 5:15:41 AM3/30/12
to Norbert Roos, golan...@googlegroups.com
On Fri, Mar 30, 2012 at 10:08 PM, Norbert Roos <nr...@webware-experts.de> wrote:
> Is it thread-safe, too? When one go routine is iterating over the map, and
> another one is deleting from it?

No, it's not. Reading from multiple goroutines is fine, but if one
wants to write you need to synchronize somehow.

- Evan

Reply all
Reply to author
Forward
0 new messages