问题① for-range线程阻塞
// 单向只写通道
func writeONLY(c chan<- int) {
	for i := 0; i < 10; i++ {
		c <- i
	}
}
// 单向只读通道
func readONLY(c <-chan int) {
	for v := range c {
		fmt.Println(v)
	}
}
// 测试效果,调用test1()
func test1() {
	ch1 := make(chan int, 10)
	writeONLY(ch1)
	//close(ch1)
	readONLY(ch1)
}
0 1 2 3 4 5 6 7 8 9 fatal error: all goroutines are asleep - deadlock!

原因

在写完数据后没有关闭管道,导致在for-range遍历的时候协程阻塞了

解决方案

如果使用for-range遍历一定要记得写完数据后关闭通道

问题② ok-idiom线程阻塞
// 单向只写通道
func writeONLY(c chan<- int) {
	for i := 0; i < 10; i++ {
		c <- i
	}
}
// 用ok-idiom模式从管道中取值的话,写完数据后必须要关闭通道,否则阻塞
func readONLY2(c <-chan int) {
	for {
		v, ok := <-c
		if !ok {
			break
		}
		fmt.Println(v)
	}
}
func test2() {
	ch1 := make(chan int, 10)
	writeONLY(ch1)
	//close(ch1)
	readONLY2(ch1)
}
0 1 2 3 4 5 6 7 8 9 fatal error: all goroutines are asleep - deadlock!

原因

ok-idiom的方式遍历和for-range一样,如果读不到管道中的数据会阻塞协程

解决方案

写完数据后关闭管道

问题③ fori遍历管道不阻塞,但死循环
// 单向只写通道
func writeONLY(c chan<- int) {
	for i := 0; i < 10; i++ {
		c <- i
	}
}
// 如果不关闭通道,还是可以从管道中读取类型的默认零值,无限循环的读
func readONLY3(c <-chan int) {
	for {
		v := <-c
		fmt.Println(v)
	}
}
func test3() {
	ch1 := make(chan int, 10)
	writeONLY(ch1)
	//close(ch1)
	readONLY3(ch1)
}

出现问题:死循环

原因

fori的方式循环从管道中取数据,如果管道中没有数据了,会从管道中读取管道类型的默认零值

解决方案

写完数据后关闭管道

总结

for-range和ok-idiom的方式遍历如果不关闭管道会发生error,fori遍历会死循环
根据业务需求,写完数据后关闭管道是个好习惯