以下代码:package mainimport ( "fmt" "strings")var data = []string{ "The yellow fish swims slowly in the water", "The brown dog barks loudly after a drink ...", "The dark bird bird of prey lands on a small ...",}func main() { histogram := make(map[string]int) words := make(chan string) for _, line := range data { go func(l string) { for _, w := range strings.Split(line, " ") { words <- w } }(line) } defer close(words) for w := range words { histogram[w]++ } fmt.Println(histogram)}以死锁结束:fatal error: all goroutines are asleep - deadlock!goroutine 1 [chan receive]:main.main() /tmp/sandbox780076580/main.go:28 +0x1e0我的理解是通道词会阻塞作者和读者来达到某种同步。我正在尝试为所有 goroutines(编写器)使用单个通道,并在 main 中使用单个读取器(使用“范围”命令)。我也尝试过缓冲通道 - 类似的失败。我很难理解为什么这不起作用。有什么有助于理解的技巧吗?
1 回答
绝地无双
TA贡献1946条经验 获得超4个赞
延迟直到 main 返回才执行。结果,范围words
永远阻塞。
要解决此问题,应用程序必须words
在所有 goroutine 完成发送后关闭。一种方法是使用等待组。等待组为每个 goroutine 递增,当 goroutines 退出时递减。另一个 goroutine 在组上等待并关闭通道。
func main() {
histogram := make(map[string]int)
words := make(chan string)
var wg sync.WaitGroup
for _, line := range data {
wg.Add(1)
go func(l string) {
for _, w := range strings.Split(l, " ") {
words <- w
}
wg.Done()
}(line)
}
go func() {
wg.Wait()
close(words)
}()
for w := range words {
histogram[w]++
}
fmt.Println(histogram)
}
奖励修复:问题中的 goroutine 引用了循环变量iine
而不是参数l
。
- 1 回答
- 0 关注
- 94 浏览
添加回答
举报
0/150
提交
取消