title: Reading a file concurrently
body: <p>The reading part isn't concurrent but the processing is.  I phrased the title this way because I'm most likely to search for this problem again using that phrase.  :)</p>
  
  <p>I'm getting a deadlock after trying to <em>go beyond the examples</em> so this is a learning experience for me.  My goals are these:</p>
  
  <ol>
  <li>Read a file line by line (eventually use a buffer to do groups of lines).</li>
  <li>Pass off the text to a <code>func()</code> that does some regex work.</li>
  <li>Send the results somewhere but avoid mutexes or shared variables.  I'm sending ints (always the number 1) to a channel.  It's sort of silly but if it's not causing problems I'd like to leave it like this unless you folks have a neater option.</li>
  <li>Use a worker pool to do this.  I'm not sure how I tell the workers to requeue themselves?</li>
  </ol>
  
  <p>Here is the <a href="http://play.golang.org/p/cb58p7rK7e" rel="noreferrer">playground link</a>.  I tried to write helpful comments, hopefully this makes sense.  My design could be completely wrong so don't hesitate to refactor.</p>
  
  <pre><code>package main
  
  import (
    "bufio"
    "fmt"
    "regexp"
    "strings"
    "sync"
  )
  
  func telephoneNumbersInFile(path string) int {
    file := strings.NewReader(path)
  
    var telephone = regexp.MustCompile(`\(\d+\)\s\d+-\d+`)
  
    // do I need buffered channels here?
    jobs := make(chan string)
    results := make(chan int)
  
    // I think we need a wait group, not sure.
    wg := new(sync.WaitGroup)
  
    // start up some workers that will block and wait?
    for w := 1; w &lt;= 3; w++ {
      wg.Add(1)
      go matchTelephoneNumbers(jobs, results, wg, telephone)
    }
  
    // go over a file line by line and queue up a ton of work
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
      // Later I want to create a buffer of lines, not just line-by-line here ...
      jobs &lt;- scanner.Text()
    }
  
    close(jobs)
    wg.Wait()
  
    // Add up the results from the results channel.
    // The rest of this isn't even working so ignore for now.
    counts := 0
    // for v := range results {
    //   counts += v
    // }
  
    return counts
  }
  
  func matchTelephoneNumbers(jobs &lt;-chan string, results chan&lt;- int, wg *sync.WaitGroup, telephone *regexp.Regexp) {
    // Decreasing internal counter for wait-group as soon as goroutine finishes
    defer wg.Done()
  
    // eventually I want to have a []string channel to work on a chunk of lines not just one line of text
    for j := range jobs {
      if telephone.MatchString(j) {
        results &lt;- 1
      }
    }
  }
  
  func main() {
    // An artificial input source.  Normally this is a file passed on the command line.
    const input = "Foo\n(555) 123-3456\nBar\nBaz"
    numberOfTelephoneNumbers := telephoneNumbersInFile(input)
    fmt.Println(numberOfTelephoneNumbers)
  }
  </code></pre>