我正在尝试使用for循环,它不断地将字符串发送到不同goroutine读取的不同通道。然而,它给了我错误“所有goroutines都睡着了 - 死锁!”为什么会这样?我搜索了一些答案,但我找不到这种情况的答案。
func main() {
var chans []chan string
for i := 0; i < 3; i++ {
chans = append(chans, make(chan string))
}
for i := 0; i < 3; i++ {
go sendString(chans[i])
}
for str := range chans[0] {
fmt.Print(str)
}
}
func sendString(ch chan string) {
ch <- "a"
ch <- "b"
ch <- "c"
ch <- "d"
}
错误在这里。它打印“abcd”,然后生成错误,如果我删除了打印循环,程序不会生成错误。
abcdfatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
C:/Users/YuanZheng Hu/Desktop/Go Test/test/test.go:18 +0x28d
goroutine 19 [chan send]:
main.sendString(0xc04203c120)
C:/Users/YuanZheng Hu/Desktop/Go Test/test/test.go:24 +0x42
created by main.main
C:/Users/YuanZheng Hu/Desktop/Go Test/test/test.go:15 +0x175
goroutine 20 [chan send]:
main.sendString(0xc04203c180)
C:/Users/YuanZheng Hu/Desktop/Go Test/test/test.go:24 +0x42
created by main.main
C:/Users/YuanZheng Hu/Desktop/Go Test/test/test.go:15 +0x175
exit status 2
我使用WaitGroup做了版本,但似乎不正确,并给了我同样的错误“所有goroutines都睡着了 - 死锁!”我在下面的代码中哪里做错了?
func main() {
var myWaitGroup sync.WaitGroup
ch := make(chan string)
myWaitGroup.Add(1)
go sendString(ch, &myWaitGroup)
myWaitGroup.Wait()
close(ch)
time.Sleep(1 * time.Second)
}
func sendString(ch chan string, pg *sync.WaitGroup) {
ch <- "a"
ch <- "b"
ch <- "c"
ch <- "d"
defer pg.Done()
}
答案 0 :(得分:7)
第二个for循环将阻塞,直到通道关闭,因此您需要在发送功能中将其关闭。此外,您只从第一个通道读取,因此一些数据丢失。这样做:
func main() {
var chans []chan string
for i := 0; i < 3; i++ {
chans = append(chans, make(chan string))
}
for i := 0; i < 3; i++ {
go sendString(chans[i])
}
for i := 0; i < 3; i++ {
for str := range chans[i] {
fmt.Print(str)
}
}
}
func sendString(ch chan string) {
ch <- "a"
ch <- "b"
ch <- "c"
ch <- "d"
close(ch)
}
将产生:
abcdabcdabcd
https://play.golang.org/p/7SoDKChnTbz
如果您希望根据评论使用单个频道执行此操作,那么您可以添加一个等待组,以便在所有go例程完成后关闭频道:
func main() {
c := make(chan string)
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func() {
sendString(c)
wg.Done()
}()
}
go func() {
wg.Wait()
close(c)
}()
for str := range c {
fmt.Print(str)
}
}
func sendString(ch chan string) {
ch <- "a"
ch <- "b"
ch <- "c"
ch <- "d"
}