title: Channel concurrency guarantees
body: <p>I'm writing a concurrency-safe memo:</p>
  
  <pre><code>package mu
  
  import (
      "sync"
  )
  
  // Func represents a memoizable function, operating on a string key, to use with a Mu
  type Func func(key string) interface{}
  
  // Mu is a cache that memoizes results of an expensive computation
  //
  // It has a traditional implementation using mutexes.
  type Mu struct {
      // guards done
      mu   sync.RWMutex
      done map[string]chan bool
      memo map[string]interface{}
      f    Func
  }
  
  // Get a string key if it exists, otherwise computes the value and caches it.
  //
  // Returns the value and whether or not the key existed.
  func (c *Mu) Get(key string) (interface{}, bool) {
      c.mu.RLock()
      _, ok := c.done[key]
      c.mu.RUnlock()
      if ok {
          return c.get(key), true
      }
  
      c.mu.Lock()
      _, ok = c.done[key]
      if ok {
          c.mu.Unlock()
      } else {
          c.done[key] = make(chan bool)
          c.mu.Unlock()
  
          v := c.f(key)
          c.memo[key] = v
  
          close(c.done[key])
      }
      return c.get(key), ok
  }
  
  // get returns the value of key, blocking on an existing computation
  func (c *Mu) get(key string) interface{} {
      &lt;-c.done[key]
      v, _ := c.memo[key]
      return v
  }
  </code></pre>
  
  <p>As you can see, there's a mutex guarding the <code>done</code> field, which is used
  to signal to other goroutines that a computation for a key is pending or done. This avoids duplicate computations (calls to <code>c.f(key)</code>) for the same key.</p>
  
  <p>My question is around the guarantees of this code; by ensuring that the computing goroutine closes the channel after it writes to <code>c.memo</code>, does this guarantee that other goroutines that access <code>c.memo[key]</code> after a  blocking call to <code>&lt;-c.done[key]</code> are guaranteed to see the result of the computation?</p>