Считывающая часть не является параллельной, но обрабатывается. Я сформулировал название таким образом, потому что я, скорее всего, снова буду искать эту проблему, используя эту фразу.:)
Я собираюсь зайти в тупик, пытаясь выйти за рамки примеров, поэтому для меня это опыт обучения. Мои цели таковы:
- Прочитайте файл по строкам (в конечном итоге используйте буфер для создания групп строк).
- Отпустите текст в
func()
, который выполняет некоторое регулярное выражение. - Присылайте результаты где-нибудь, но избегайте мьютексов или общих переменных. Я посылаю ints (всегда число 1) в канал. Это вроде глупо, но если это не вызывает проблем, я бы хотел оставить это так, если у вас нет опциона.
- Используйте рабочий пул для этого. Я не уверен, как я говорю рабочим, чтобы они сами требовали?
Вот ссылка playground. Я попытался написать полезные комментарии, надеюсь, это имеет смысл. Мой дизайн может быть совершенно неправильным, поэтому не стесняйтесь рефакторировать.
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 <= 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 <- 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 <-chan string, results chan<- 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 <- 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)
}