1. channel的关闭

使用内置函数close可以关闭channel,当channel关闭后,就不能再向channel写数据了,但是仍然可以从该channel读取数据

案例演示:

package main
import (
	"fmt"
)

func main() {
	intChan := make(chan int, 3)
	intChan <- 100
	intChan <- 200
	close(intChan) // close
	// 这时不能够再向channel写入
	// intChan <- 300
	fmt.Println("okok")
	// 当管道关闭后,读取数据是可以的
	n1 := <- intChan
	fmt.Println(n1)
}

2. 管道的遍历

channel 支持 for-range的方式进行遍历,请注意两个细节

1)在遍历时,如果channel没有关闭,则会出现deadlock 的错误

2)在遍历时,如果channel已经关闭,则会正常遍历数据,遍历完后,就会退出遍历

3)不使用for进行遍历,假如使用for进行遍历长度为100的channel数据,最后拿出来的只有50条

3. channel遍历和关闭的案例演示

看代码演示:

package main
import (
	"fmt"
)

func main() {
	intChan := make(chan int, 100)
	for i := 0; i < 100; i++ {
		intChan <- i * 2 // 放入100个数据到管道
	}

	// 遍历管道时,不能使用普通的for循环结构
	// for i := 0; i < len(intChan); i++ {
	// }
	
	// 如果在遍历时没有关闭channel,则会出现deadlock错误
	// close(intChan)
	// for v := range intChan {
	// 	fmt.Println("v=",v)
	// }
}

4.应用案例1——goroutine和channel协同工作的

1)开启一个writeData协程,向管道intChan中写入50个整数

2)开启一个readData协程,从管道intChan中读取writeData写入的数据

3)注意:writeData和readData操作的是同一个管道

4)主线程需要等待writeData和readData协程都完成工作后才能退出【管道】

思路分析:

x, ok := <- c
package main
import (
	"fmt"
)

// write Data
func writeData(intChan chan int) {
	for i := 1; i <= 50; i++ {
		// 放入数据
		intChan<- i
		fmt.Println("writeData",i)
	}
	close(intChan)
}
// read data
func readData(intChan chan int, exitChan chan bool) {
	for {
		v, ok := <- intChan
		if !ok {
			break
		}
		fmt.Printf("readData 读到数据=%v",v)
	}
	// readData  读取完数据后,即任务完成
	exitChan <- true
	close(exitChan)
}
func main() {
	// 创建两个管道
	intChan := make(chan int, 50)
	exitChan := make(chan bool, 1)
	go writeData(intChan)
	go readData(intChan, exitChan)
	for {
		_,ok := <- exitChan
		if !ok {
			break
		}
	}
}

5.应用案例2——阻塞

 如果写的快,而读的快的话也不会发生死锁,如:给channel1长度为10,再给一个方法写入channel1数据100个,再给一个方法读取channel1数据,如果写的快的话,达到10的时候,编译器会发现channe1写满了就不会继续写入,也就是不会阻塞,等读取了数据后,channel1中的数据不为10的时候,再接着写入。编译器底层会处理。

案例如下:

package main
import (
	"fmt"
	"time"
)

// write Data
func writeData(intChan chan int) {
	for i := 1; i <= 50; i++ {
		// 放入数据
		intChan<- i
		fmt.Println("writeData",i)
	}
	close(intChan)
}
// read data
func readData(intChan chan int, exitChan chan bool) {
	for {
		time.Sleep(time.Second)
		v, ok := <- intChan
		if !ok {
			break
		}
		fmt.Printf("readData 读到数据=%v\n",v)
	}
	// readData  读取完数据后,即任务完成
	exitChan <- true
	close(exitChan)
}
func main() {
	// 创建两个管道
	intChan := make(chan int, 10)
	exitChan := make(chan bool, 1)
	go writeData(intChan)
	go readData(intChan, exitChan)
	for {
		_,ok := <- exitChan
		if !ok {
			break
		}
	}
}