今天采用WaitGroup来实现协程,发现range chanel会死锁,代码如下:package main

import "sync"
import "fmt"

func main() {
var wg sync.WaitGroup
wg.Add(3)
resultChannel := make(chan int, 3)
routineFunc := func(i int) {
defer wg.Done()
resultChannel <- i
fmt.Println("push to channel,", i)
}

for i := range []int{1, 2, 3} {
go routineFunc(i)
}
wg.Wait()

fmt.Println("wg.wait")

for res := range resultChannel {
fmt.Println("got from channel,", res)
}
}

运行时会出现错误:

  push to channel, 0
  push to channel, 1
  push to channel, 2
  wg.wait
  got from channel, 0
  got from channel, 1
  got from channel, 2
  fatal error: all goroutines are asleep - deadlock!

 

原因是:for range是阻塞式读取channel,只有channel close之后才会结束,否则会一直读取,通道里没有值了,还继续读取就会阻塞,程序就会报死锁。

改成如下即可:

 

package main

import "sync"
import "fmt"

func main() {
var wg sync.WaitGroup
wg.Add(3)
resultChannel := make(chan int, 3)
routineFunc := func(i int) {
defer wg.Done()
resultChannel <- i
fmt.Println("push to channel,", i)
}

for i := range []int{1, 2, 3} {
go routineFunc(i)
}
wg.Wait()
close(resultChannel)

fmt.Println("wg.wait")

for res := range resultChannel {
fmt.Println("got from channel,", res)
}
}