Go 为什么在这个函数中使用通道?

Go 为什么在这个函数中使用通道?,go,channel,goroutine,Go,Channel,Goroutine,我正在研究使用go例程的时机,我看到了下面粘贴的示例,从第61行到第65行。但我不明白在这里使用频道的目的 他似乎正在迭代通道以检索go例程中的msg。 但是为什么不直接使用字符串数组呢 58 func findConcurrent(goroutines int,topic string,docs[]string)int{ 59变量在64中找到 60 61通道:=制造(成串、透镜(文件)) 62对于u2;,单据:=范围单据{ 63 ch作者似乎只是在用一个人为的例子来说明频道是如何工作的。也许他

我正在研究使用go例程的时机,我看到了下面粘贴的示例,从第61行到第65行。但我不明白在这里使用频道的目的

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

58 func findConcurrent(goroutines int,topic string,docs[]string)int{
59变量在64中找到
60
61通道:=制造(成串、透镜(文件))
62对于u2;,单据:=范围单据{

63 ch作者似乎只是在用一个人为的例子来说明频道是如何工作的。也许他应该提出一个更现实的例子。但他确实说:

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


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

这段代码提供了一个分发工作(在文档中查找字符串)的示例在多个goRoutines中。基本上,代码是启动
goRoutines
,并通过一个频道将文档提供给他们进行搜索

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

可以使用一个字符串数组和一个变量(我们称之为
count
)来跟踪数组中的项目。您可以使用一些代码,如(有点冗长,以说明一点):

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


进程的同步很复杂,问题可能很难调试。使用通道会对您隐藏很多这种复杂性,并使您的代码更有可能按预期工作(它不能解决所有问题;请注意使用
atomic.AddInt64(&found,lFound)
在示例代码中,以防止由于多个go例程同时写入一个变量而导致的另一个潜在问题).

我不知道作者为什么选择在那里使用频道。我同意直接使用片段可能是有意义的。也许这只是演示频道的借口。如果没有原始博文的链接,或者直接询问作者,就只能猜测。使用字符串片段肯定会造成竞争条件当在go例程中使用时。使用go例程读取/写入值范围时,最好使用通道。PS:U也可以使用切片,但需要使用互斥体,在go例程中使用通道更好case@RaviChandak你确定吗?代码只是从
docs
切片读取,这真的会导致r吗ace条件?@mkopriva在本例中再次查看时,我同意您的看法,但是..如果文档切片本身可能可以通过调用函数进行更新或传递。如果您想简单地解释goroutine和channels是如何协同工作的,您需要使用goroutine和channels,而不是slices和for循环。当然,您可以p文档切片,并让goroutines从该切片中选取。但这种选取需要同步。如果您有N个goroutines处理N!=M的M个文档,则提供的解决方案非常简单。从作者的观点来看,通道的使用点仍然令人困惑。
for {
   if count > len(docarray) {
      break;
   }
   doc := docarray[count]
   count++
   // Process the document
}