网上关于channel的使用有很多介绍,这里不在阐述,这里主要是记录下开发中,可能存在使用channel不当造成的问题总结下, 说道这里,还是总结下channel的几个特性吧:
说道这里,还是总结下channel的几个特性吧:
-
给一个 空 channel发送数据,会造成永远阻塞
-
从一个 空 channel接收数据,会造成永远阻塞
-
给一个已经关闭的channel发送数据,会引起 panic
-
从一个已经关闭的channel接收数据,如果缓冲区中为空,则返回一个零值
-
无缓冲的channel是同步的,有缓冲的channel是异步的
废话不多说,大家看下下面的代码是如何执行的,输出结果是什么?
package main import ( "fmt" "time" ) func main() { chn := make(chan int, 1000) //定义一个1000容量的channel go func() { for i := 0; i < 10; i++ { // 向管道chn发送写入10个数字 chn <- i } }() go func() { // 开启一个携程 循环从chn中获取值 for { i, ok := <-chn if !ok { // 取值为空或零 fmt.Println("chn已经关闭") return } fmt.Println("i = ", i) } }() close(chn) // 这里直接关闭了chn fmt.Println("sucess") time.Sleep(time.Minute * 1) // 等待1分钟让携程全部执行完毕 }
上面代码最大的问题在哪里? 很明显。代码中开启了两个go携程,第一个写数据,第二个读取数据,开完两个goroutine之后main主携程直接close掉channel,
然后直接输出打印:success。
但是往已经关闭的channel写入数据会panic的。所以上面的结果输出:
sucess chn已经关闭 panic: send on closed channel goroutine 6 [running]: main.main.func1() /media/uos/G/web/demo-go/main.go:12 +0x36 created by main.main /media/uos/G/web/demo-go/main.go:10 +0x6b exit status 2