2 回答
TA贡献1776条经验 获得超12个赞
OP更新问题后更新答案
您可以只循环地图中的所有键,也许还有另一个 goroutine 不断循环所有键。显然,如果一个键没有被初始化,那么它就不会出现在 for range 循环中。对于每个键,您可以启动一个监听的 goroutine,这样它就不会阻塞,或者您可以使用缓冲通道,这样它们就不会阻塞到缓冲区限制。您也可以最好使用 waitGroup,而不是 time.Sleep(),这些仅用于这个简单的示例。
package main
import (
"fmt"
"time"
)
func main() {
m := make(map[int]chan string)
go func() {
m[0] = make(chan string)
m[0] <- "abab"
}()
time.Sleep(time.Second * 1) //sleep so the above goroutine initializes the key 0 channel
for key := range m{ //loop on all non-nil keys
fmt.Println(key)
go func(k int){ // goroutine to listen on this channel
fmt.Println(<- m[k])
}(key)
}
time.Sleep(time.Second * 1) //sleep so u can see the effects of the channel recievers
}
旧答案
流量就是这样。主 goroutine 启动。地图已创建。主 goroutine 遇到另一个 goroutine。它产生了 goroutine 并继续它的生活。然后遇到这条线,fmt.Println(<-m[0]),这是一个问题,因为地图确实初始化了,但是地图本身的通道没有初始化!当主 goroutine 到达fmt.Println(<-m[0])时,另一个 goroutine 还没有初始化通道!所以这是一个简单的修复,只需在生成 goroutine 之前初始化通道,你就可以开始了!
package main
import "fmt"
func main() {
m := make(map[int]chan string)
m[0] = make(chan string)
go func() {
m[0] <- "abab"
}()
fmt.Println(<-m[0])
}
编辑:请注意这fmt.Println(<-m[0])是阻塞的,这意味着如果在另一个 goroutine 中,您不在通道上发送,您也会陷入死锁,因为您试图在没有人实际发送的情况下在通道上接收。
TA贡献1880条经验 获得超4个赞
您需要同步通道的创建。
就目前而言,您的主线程到达时<-m[0]
仍然m[0]
是一个未初始化的通道,并且在未初始化的通道上接收永远阻塞。
您的 go 例程创建了一个新通道并将其放入m[0]
,但主要的 go 例程已经在侦听先前的零值。在这个新通道上发送也会永远阻塞,因为它没有读取任何内容,所以所有 goroutine 都会阻塞。
要解决这个问题,请移到m[0] = make(chan string)
你的 go 例程之上,这样它就会同步发生。
- 2 回答
- 0 关注
- 83 浏览
添加回答
举报