func main() {
	boolChannel()
}
func boolChannel()  {
	ch1 := make(chan int)
	ch2 := make(chan bool)
	go func() {
		for i:=0;i<5;i++ {
			ch1 <- i
		}
		ch2 <- true	//标识位写入 true
	}()
	go func() {
		for x:= range ch1{
			fmt.Println(x)
		}
	}()
	<-ch2 //阻塞标识位
}
为什么这个输出结果一会是 0,1,2,3,一会是 0,1,2,3,4
按道理来说,我在主进程一直阻塞了,应该等 goroutine 全部打印完才对呀,百思不得其解
     1 
                    
                    tottea      2020-05-17 11:16:17 +08:00 
                    
                    应该是 fmt.Println(x)这里的耗时吧,ch1 <- 4 完了之后马上 ch2 <- true,主协程一直阻塞后马上执行<-ch2,这时候			fmt.Println(4)这里卡在主协程结束前后,所以会有不稳定的情况 
                我的理解是这样  | 
            
     2 
                    
                    beidounanxizi      2020-05-17 11:16:55 +08:00 
                    
                    这不是很正常啊  打印的 goroutine 你有没有同步机制 去保证 先于 main goroutine 结束 ? 
                去看看 GMP 的调度把  | 
            
     3 
                    
                    smallyu      2020-05-17 11:19:11 +08:00 
                    
                    ch2 <- true 上面加一行 time.Sleep(1 * time.Second) 
                 | 
            
     4 
                    
                    thet      2020-05-17 11:20:51 +08:00 via iPhone 
                    
                    <-ch2 接受到值,就往后执行了,这时候第二个 goroutine 可能还没执行完成 
                 | 
            
     5 
                    
                    ysmood      2020-05-17 11:23:02 +08:00 
                    
                    删掉 ch2 <- true 就可以了 
                 | 
            
     6 
                    
                    wangsongyan      2020-05-17 11:23:44 +08:00 via iPhone 
                    
                    打印完后再往 ch2 写值 
                 | 
            
     7 
                    
                    cabing      2020-05-17 11:31:01 +08:00 
                    
                    加入 wait group 或者 context,不能保证你的 print 在 main 之前 
                 | 
            
     8 
                    
                    CEBBCAT      2020-05-17 11:36:51 +08:00 
                    
                    这两个 go 出去的 func 并没有形成锁,只有第一个 func 和 boolChannel 形成了锁,所以你能确保的是全部写入后才会终结 boolChannel 的执行,但 fmt.Println(x)一定执行吗?不一定,因为可能正准备 fmt.Println(x),这个 goroutine 就被切到等待队列里了 
                (我不知道应不应该使用锁这个名词,基础忘掉了大半,欢迎拍砖)  | 
            
     9 
                    
                    gamexg      2020-05-17 11:44:19 +08:00 via Android 
                    
                    第一个 go 协程结束时关闭信道 
                第二个协程直接在主线程执行。 ch2 可以去掉。  | 
            
     10 
                    
                    reus      2020-05-17 12:10:58 +08:00    ch2 <- true 改成 close(ch1) 
                ch2 <- true 移到第二个 for 后面  | 
            
     12 
                    
                    damingxing      2020-05-17 12:19:44 +08:00 
                    
                    4 进入 ch1 后,true 进入 ch2, 
                情况 1:主程序先得到 ch2,第二个 func 还没来得及得到 ch1 或者没来得及打印, 程序就退出 输出 0,1,2,3 情况 2:第二个 func 得到 ch1 并且打印,主程序还没来得及得到 ch2,输出 0,1,2,3,4  | 
            
     13 
                    
                    damingxing      2020-05-17 12:23:39 +08:00 
                    
                    ch2 <- true	//标识位写入 true 
                这句放到第二个 func 后面就行了  | 
            
     14 
                    
                    ifconfig   OP @damingxing 通俗易懂理解了,其实就是想看看不通过 waitGroup 能不能解决,多谢~ 
                 | 
            
     15 
                    
                    damingxing      2020-05-17 12:28:05 +08:00 
                    
                    @ifconfig 可以的,按照云风大侠的说法,通道是最佳解决方案 
                 | 
            
     16 
                    
                    useben      2020-05-17 12:29:01 +08:00 
                    
                    一般是发送 goroutine 是 close 发送的 chan,接收 goroutine 是关闭阻塞 chan 
                这样的好处是不会造成 goroutine 泄露,发送完 close,接收 for chan 还是可以接收完数据的,会自己退出,这时候 close 或者发送信号到退出 chan 。  |