title: Concurrent access to maps with 'range' in Go
body: <p>The "<a href="https://blog.golang.org/go-maps-in-action" rel="noreferrer">Go maps in action</a>" entry in the Go blog states: </p>
  
  <blockquote>
    <p>Maps are not safe for concurrent use: it's not defined what happens when you read and write to them simultaneously. If you need to read from and write to a map from concurrently executing goroutines, the accesses must be mediated by some kind of synchronization mechanism. One common way to protect maps is with sync.RWMutex.</p>
  </blockquote>
  
  <p>However, one common way to access maps is to iterate over them with the <code>range</code> keyword. It is not clear if for the purposes of concurrent access, execution inside a <code>range</code> loop is a "read", or just the "turnover" phase of that loop.  For example, the following code may or may not run afoul of the "no concurrent r/w on maps" rule, depending on the specific semantics / implementation of the <code>range</code> operation:</p>
  
  <pre><code> var testMap map[int]int
   testMapLock := make(chan bool, 1)
   testMapLock &lt;- true
   testMapSequence := 0
  </code></pre>
  
  <p>...</p>
  
  <pre><code> func WriteTestMap(k, v int) {
      &lt;-testMapLock
      testMap[k] = v
      testMapSequence++
      testMapLock&lt;-true
   }
  
   func IterateMapKeys(iteratorChannel chan int) error {
      &lt;-testMapLock
      defer func() { 
         testMapLock &lt;- true
      }
      mySeq := testMapSequence
      for k, _ := range testMap {
         testMapLock &lt;- true
         iteratorChannel &lt;- k
         &lt;-testMapLock
         if mySeq != testMapSequence {
             close(iteratorChannel)
             return errors.New("concurrent modification")
         }
      }
      return nil
   }
  </code></pre>
  
  <p>The idea here is that the <code>range</code> "iterator" is open when the second function is waiting for a consumer to take the next value, and the writer is not blocked at that time.   However, it is never the case that two reads in a single iterator are on either side of a write - this is a "fail fast" iterator, the borrow a Java term.</p>
  
  <p>Is there anything anywhere in the language specification or other documents that indicates if this is a legitimate thing to do, however?   I could see it going either way, and the above quoted document is not clear on exactly what consititutes a "read". The documentation seems totally quiet on the concurrency aspects of the <code>for</code>/<code>range</code> statement. </p>
  
  <p>(Please note this question is about the currency of <code>for/range</code>, but not a duplicate of: <a href="https://stackoverflow.com/questions/34080734/golang-concurrent-map-access-with-range">Golang concurrent map access with range</a> - the use case is completely different and I am asking about the precise locking requirement wrt the 'range' keyword here!)</p>