
下面的代码,注释的地方,通过 for range 遍历时 go show1(x) 可以正常输出 1 到 10
但是使用 for 遍历时 go show2(x) 有时候不能完整的输出,只能输出 1 到 9 ,会丢失一部分
想问下是否我代码中 goroutine 使用的有问题,还是说只能通过 for range 给 goroutine 传值?
var ( wg = sync.WaitGroup{} ) func show1(x int) { defer wg.Done() fmt.Println(x) } func show2(ch chan int) { defer wg.Done() c := <-ch fmt.Println(c) } func main() { ch1 := make(chan int, 40) for i := 1; i < 11; i++ { ch1 <- i } close(ch1) // for x := range ch1 { // wg.Add(1) // go show1(x) // } for j := 1; j < len(ch1)+1; j++ { wg.Add(1) go show2(ch1) } wg.Wait() } 1 k9982874 2021-11-15 11:35:35 +08:00 这代码嘈点太多。。自己再仔细自查一下 |
3 40EaE5uJO3Xt1VVa 2021-11-15 11:39:33 +08:00 @k9982874 求指点 |
4 FakNoCNName 2021-11-15 11:41:42 +08:00 先考虑算法问题。 len(ch1)是个动态的值,你每次读取、写入数据都会变化。 按照你写的算法,最多输出 10~6 这几个数字,很好奇为什么只丢了一个? 改成下面的试试: n := len(ch1) for j := 0; j < n; j++ { wg.Add(1) go show2(ch1) } |
5 LemonK 2021-11-15 11:41:47 +08:00 len(ch1) 会变小。 |
6 clearT 2021-11-15 11:45:47 +08:00 就是上面楼层说的问题,len(ch1) 是个动态的值,按照你那种写法也不一定只会丢一个,和 goroutine 的调度也有关系,所以运行结果是不确定的,丢几个都有可能 |
7 reber0ask OP @LemonK 如果只向 chan 中传入了 1 到 10 的话可能丢失一个数字 10 ,如果传入 1 到 20 的话可能只能输出 1 到 17 、18 这样子, 按你的代码在 for 的外面使用 n := len(ch1)的话是没有问题的,确实可以输出 1 到 10 ,不会丢失数据 |
8 reber0ask OP |
9 mmrindextt 2021-11-15 13:41:22 +08:00 for 中 go , 就值得细品了 |
10 zjj19950716 2021-11-15 16:16:11 +08:00 @mmrindextt 展开讲讲 |
11 snowlyg 2021-11-16 09:29:13 +08:00 又看到这个问题,好想吐槽一下。哈哈 |
12 wakaka 2021-11-16 09:57:55 +08:00 不得要领 |