title: How to wait for *any* of a group of goroutines to signal something without requiring that we wait for them to do so
body: <p>There are plenty of examples of how to use WaitGroup to wait for <em>all</em> of a group of goroutines to finish, but what if you want to wait for any <em>one</em> of them to finish without using a semaphore system where some process <em>must</em> be waiting? For example, a producer/consumer scenario where multiple producer threads add multiple entries to a data structure while a consumer is removing them one at a time. In this scenario:</p>
  
  <ul>
  <li><strong>We can't just use the standard producer/consumer semaphore system</strong>, because production:consumption is not 1:1, and also because the data structure acts as a cache, so the producers can be "free-running" instead of blocking until a consumer is "ready" to consume their product.</li>
  <li>The data structure may be emptied by the consumer, in which case, <strong>the consumer wants to wait until any one of the producers finishes</strong> (meaning that there might be new things in the data structure)</li>
  </ul>
  
  <p><strong>Question: Is there a standard way to do that?</strong></p>
  
  <p>I've only been able to devise two methods of doing this. Both by using channels as semaphores:</p>
  
  <pre><code>var unitary_channel chan int = make(chan int, 1)
  
  func my_goroutine() {
     // Produce, produce, produce!!!
     unitary_channel&lt;-0 // Try to push a value to the channel
     &lt;-unitary_channel // Remove it, in case nobody was waiting
  }
  
  func main() {
     go my_goroutine()
     go my_goroutine()
     go my_goroutine()
     for len(stuff_to_consume) { /* Consume, consume, consume */ }
     // Ran out of stuff to consume
     &lt;-unitary_channel
     unitary_channel&lt;-0 // To unblock the goroutine which was exiting
     // Consume more
  }
  </code></pre>
  
  <p>Now, this simplistic example has some glaring (but solvable issues), like the fact that main() can't exit if there wasn't at least one go_routine() still running.</p>
  
  <p>The second method, instead of requiring producers to remove the value they just pushed to the channel, uses <em>select</em> to allow the producers to exit when the channel would block them.</p>
  
  <pre><code>var empty_channel chan int = make(chan int)
  
  func my_goroutine() {
     // Produce, produce, produce!!!
     select {
        case empty_channel &lt;- 0: // Push if you can
        default:  // Or don't if you can't
     }
  }
  
  func main() {
     go my_goroutine()
     go my_goroutine()
     go my_goroutine()
     for len(stuff_to_consume) { /* Consume, consume, consume */ }
     // Ran out of stuff to consume
     &lt;-unitary_channel
     // Consume more
  }
  </code></pre>
  
  <p>Of course, this one will <em>also</em> block main() forever if all of the goroutines have already terminated. <strong>So, if the answer to the first question is "No, there's no standard solution to this other than the ones you've come up with", is there a compelling reason why one of these should be used instead of the other?</strong></p>