为什么要在此功能中使用频道?

我正在研究a blog上有关使用go例程的时间的信息,我看到了下面粘贴的示例(从61行到65行)。但是我没有达到这里使用channel的目的。

似乎他正在迭代通道以检索go-routine中的msg。 但是为什么不直接使用字符串数组呢?

58 func findConcurrent(goroutines int,topic string,docs []string) int {
59     var found int64
60
61     ch := make(chan string,len(docs))
62     for _,doc := range docs {
63         ch <- doc
64     }
65     close(ch)
66
67     var wg sync.WaitGroup
68     wg.Add(goroutines)
69
70     for g := 0; g < goroutines; g++ {
71         go func() {
72             var lFound int64
73             for doc := range ch {
74                 items,err := read(doc)
75                 if err != nil {
76                     continue
77                 }
78                 for _,item := range items {
79                     if strings.Contains(item.Description,topic) {
80                         lFound++
81                     }
82                 }
83             }
84             atomic.AddInt64(&found,lFound)
85             wg.Done()
86         }()
87     }
88
89     wg.Wait()
90
91     return int(found)
92 }
jackybye 回答:为什么要在此功能中使用频道?

此代码提供了在多个goRoutine之间分配工作(在文档内查找字符串)的方法的示例。基本上,代码是从goroutines开始,然后向其提供文档以通过渠道进行搜索。

  

但是为什么不直接使用字符串数组呢?

可以使用字符串数组和变量(将其称为count)来跟踪您要处理的数组中的哪个项目。您将有一些类似的代码(有点冗长地演示了一点):

for {
   if count > len(docarray) {
      break;
   }
   doc := docarray[count]
   count++
   // Process the document
}

但是您会遇到同步问题。例如,如果两个go例程(在不同的处理器内核上运行)同时到达if count > len(docarray),会发生什么情况?如果没有防止这种情况发生的方法,它们可能都将最终处理片中的同一项目(并且可能会跳过下一个元素,因为它们都运行count++)。

流程的同步非常复杂,问题很难调试。使用通道会给您隐藏很多此类复杂性,并使您的代码按预期工作的可能性更大(它不能解决所有问题;请注意在示例代码中使用atomic.AddInt64(&found,lFound)来防止可能发生的另一个潜在问题多个go例程同时写入一个变量的结果)。

,

作者似乎只是在使用一个人为设计的示例来说明渠道是如何工作的。也许他想出一个更现实的例子。但是他确实说:

  

注意:编写并发版本的add时,可以采用几种方法和选项。现在不要挂在我的特定实现上。如果您的可读性更好的版本具有相同或更好的性能,我希望与您分享。

因此,很明显,他并没有试图为这份工作编写最好的代码,只是为了说明他的观点。

本文链接:https://www.f2er.com/3139274.html

大家都在问