eol_tech · 提问于2021.05.28浏览量:599问题描述:
打算使用goroutine并发执行,做了个demo测试,发现goroutine打印的切片大小和切片实际数据不一致
代码如下:
package mainimport ("fmt""sync")func main() {var numsInt []intresponseChannel := make(chan int, 10)go func() {for rc := range responseChannel {numsInt = append(numsInt, rc)}}()wg := &sync.WaitGroup{}for i := 0; i < 10; i++ {wg.Add(1)go func(num int, c chan int) {defer wg.Done()data := numc <- data}(i, responseChannel)}wg.Wait()// 这里打印的len(numsInt) < 10fmt.Println("len(numsInt) = ", len(numsInt))// 这里打印了10个数字fmt.Println("numsInt = ", numsInt)// 这里打印的len(numsInt) == 10fmt.Println("len(numsInt) = ", len(numsInt))}

通道的消费应该还没完成。在wait后加上close(responseChannel),执行会显示panic (send to closed channel)

你的代码里面只等待生产者往channel里面发送完毕,但没有等待消费者从channel里面消费完所有数据,当你打印numsInt的时候消费协程还在写入。当channel是带缓冲的结果会更差,因为生产者往channel里面发送数据没有阻塞,更不会跟消费者同步了。 多加一个消费者的同步代码就可以了

这个符合预期吧, 首先你的 channel 是带有 10 个缓存的 其次,for-loop 里面的 goroutine 是按照的预期向 channel 里面写入数据,并且 wg.Wait() 之后一定是 10 个数据都已经写入了 channel。 但是很遗憾,你没有 wait 最上面的 消费者 goroutine ,也就是说,这个时候还有可能 channel 里面有尚未消费的内容。消费的 goroutine 并没有参与到 wg 的同步逻辑里 你可以改正如下逻辑再进行一次尝试: