阅读部分不是并发的,但处理是并发的。我用这种方式来命名标题,因为我最有可能使用该短语再次搜索此问题。:)
尝试 超越示例 之后,我陷入僵局,因此这对我来说是一种学习经验。我的目标是:
func()
这是游乐场的链接。我试图写出有用的评论,希望这很有道理。我的设计可能是完全错误的,所以请毫不犹豫地进行重构。
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) }
您快要准备好了,只需要在goroutine的同步上做一些工作即可。您的问题是您试图在相同的例程中提供解析器并收集结果,但这无法完成。
我提出以下建议:
相关更改如下所示:
// Go over a file line by line and queue up a ton of work go func() { scanner := bufio.NewScanner(file) for scanner.Scan() { jobs <- scanner.Text() } close(jobs) }() // Collect all the results... // First, make sure we close the result channel when everything was processed go func() { wg.Wait() close(results) }() // Now, add up the results from the results channel until closed counts := 0 for v := range results { counts += v }
在操场上完全可用的示例:http : //play.golang.org/p/coja1_w-fY
值得补充的是,您不一定需要WaitGroup实现相同的目标,您需要知道的是何时停止接收结果。例如,可以通过扫描仪广告(在频道上)读取多少行,然后收集器仅读取指定数量的结果(您也需要发送零)来实现。
WaitGroup