Is it always safe to delete map entries during iteration?

1,856 views
Skip to first unread message

David Anderson

unread,
Nov 4, 2012, 4:55:56 PM11/4/12
to golang-nuts
I'm iterating through map entries, and occasionally, I delete the key I'm currently on. That is:

for addr, shutdown := range children {
  if shouldShutdown(addr) {
    close(shutdown)
    del(children[addr])
  }
}

The spec at http://golang.org/ref/spec#For_statements states that deleting entries not already iterated over is safe, and behaves as you'd expect. However, unless I missed it, it doesn't state whether or not it is safe to delete the current entry, as I do above.

Given Go's sensible design, I'm guessing that it was a property too trivial to state, but C++ has made me paranoid about how iterators react to mutation.

So, is the above defined behavior? If so, would it be worth explicitly pointing out in the spec?

- Dave

Jan Mercl

unread,
Nov 4, 2012, 5:29:05 PM11/4/12
to David Anderson, golang-nuts
It's implied from the fact that every key is visited only once. While
deleting a non visited key is defined to be safe explicitly, deleting
an already visited has no effect on the iteration b/c the key was
already seen.

-j
> --
>
>

Kevin Gillette

unread,
Nov 4, 2012, 11:50:40 PM11/4/12
to golan...@googlegroups.com, David Anderson
On Sunday, November 4, 2012 3:29:34 PM UTC-7, Jan Mercl wrote:
It's implied from the fact that every key is visited only once. While
deleting a non visited key is defined to be safe explicitly, deleting
an already visited has no effect on the iteration b/c the key was
already seen.

In that case, the spec may benefit by being amended with a phrase along the lines of:

Any mutation of the map during iteration, by the iterating goroutine or in synchronization with the iteration, is safe.

Jan Mercl

unread,
Nov 5, 2012, 4:08:00 AM11/5/12
to Kevin Gillette, golang-nuts, David Anderson
On Mon, Nov 5, 2012 at 5:50 AM, Kevin Gillette
<extempor...@gmail.com> wrote:
> Any mutation of the map during iteration, by the iterating goroutine or in
> synchronization with the iteration, is safe.

That's problematic. Consider http://play.golang.org/p/kc38uNdmsK vs
http://play.golang.org/p/5XJER_DOTA

Both programs behave perfectly per specs, but I would not call such
mutation "safe" as it produces unpredictable results.

-j

si guy

unread,
Nov 5, 2012, 6:24:25 AM11/5/12
to golan...@googlegroups.com
Wow, that looks like fun.

Still memory safe though right? I mean, if your app is agnostic to this odd behaviour.

Kevin Gillette

unread,
Nov 5, 2012, 6:58:32 AM11/5/12
to golan...@googlegroups.com, Kevin Gillette, David Anderson
I'll clarify "safe" to be safe from memory/data-struct corruption, if that's true. There are implementations for other languages in which iteration over a map-like object will de-sync the 'iterator' and leave its pointer dangling -- their usual fix is to include some kind of ismodified flag or generation, and have the iterator abort if it detects an out-of-sync condition.

Some programmers coming to Go will want to be explicitly told that they can't segfault their app by modifying a map whilst iterating over it.
Reply all
Reply to author
Forward
0 new messages