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

我正在研究一篇关于使用 go-routines 的时机的博客,我看到了下面粘贴的示例,从第 61 行到第 65 行。但我不明白这里使用通道的目的。

看来他正在迭代通道以检索 go-routine 内的消息。但为什么不直接使用字符串数组呢?

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 }


青春有我
浏览 124回答 3
3回答

米脂

此代码提供了在多个 goRoutines 之间分配工作(在文档中查找字符串)的示例。基本上,代码是启动goroutines并向他们提供文档以通过通道进行搜索。但为什么不直接使用字符串数组呢?可以使用字符串数组和变量(我们称之为count)来跟踪您正在处理的数组中的项目。你会有一些类似的代码(有点啰嗦来演示一点):for {&nbsp; &nbsp;if count > len(docarray) {&nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp;}&nbsp; &nbsp;doc := docarray[count]&nbsp; &nbsp;count++&nbsp; &nbsp;// Process the document}但是您会遇到同步问题。例如,如果两个 go 例程(在不同的处理器内核上运行)if count > len(docarray)同时到达会发生什么?如果没有什么措施来阻止这种情况,它们可能最终都会处理切片中的相同项目(并且可能会跳过下一个元素,因为它们都运行count++)。进程同步很复杂,而且问题很难调试。使用通道可以让您隐藏很多复杂性,并使您的代码更有可能按预期工作(它并不能解决所有问题;请注意在atomic.AddInt64(&found, lFound)示例代码中使用 来防止多个 go 例程导致的另一个潜在问题同时写入变量)。

犯罪嫌疑人X

他正在使用缓冲通道,所以我不认为通道在这里做任何特殊的工作,任何普通的字符串切片也会做同样的事情。

小唯快跑啊

作者似乎只是用一个人为的例子来说明渠道是如何工作的。也许他需要想出一个更现实的例子。但他确实说:注意:编写并发版本的 add 时可以采用多种方法和选项。此时不要纠结于我的特定实现。如果您有一个更具可读性且性能相同或更好的版本,我很乐意与您分享。因此,很明显他并不是想为这项工作编写最好的代码,只是为了说明他的观点。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go