chan在go语言中相当于一个文件操作符,使用完成之后需要使用Close()函数关闭。
下面这段代码有两个chan,ch1是一个chan int类型,ch2是一个chan bool类型,ch1被write()函数写入10个数,被read()函数读取,ch2其实是为了防止main所在的goroutine提前退出用的。
我们分别在写完之后Close()和不Close()看看有什么不同。
package main
import "fmt"
func read(ch1 chan int,ch2 chan bool){
for{
fmt.Printf("read a int is %d\n",<-ch1)
}
ch2 <- true
}
func write(ch chan int){
for i:=0;i<10;i++{
ch <- i
}
//close(ch)
}
func main() {
ch1 := make(chan int)
ch2 := make(chan bool)
go write(ch1)
go read(ch1,ch2)
<-ch2
}
下面是不close()的运行结果:
从执行结果可以看到,当我们将10个数写完之后,如果不close()ch1,read就会阻塞,程序中所有的协程都被阻塞,ch2无法写入,也无法读取,系统这时候检测到这种错误就会报错。
当我们把close()打开之后,再执行一遍,看看运行的结果:
我们这次可以看到close之后,read函数在读完10个数字之后,也不会阻塞会一直读取到0,ch2也不会因为没有写入和读取导致整个程序报错。所以我们每次在使用chan完成之后一定要记得关闭,这样即使我们读端没有做读完处理,程序也不会出错。
下面是这个例子的正确写法,我们在读取chan时可以根据,第二个返回值,判断写端是否关闭,如果写端关闭,则会读取到false,通过close()和读取端根据读chan第二个返回值可以确保管道在读写两端能够做到写多少读多少,程序也能很友好的退出。
package main
import "fmt"
func read(ch1 chan int,ch2 chan bool){
for{
v ,ok:= <- ch1
if ok{
fmt.Printf("read a int is %d\n",v)
}else{
ch2 <- true
}
}
}
func write(ch chan int){
for i:=0;i<10;i++{
ch <- i
}
close(ch)
}
func main() {
ch1 := make(chan int)
ch2 := make(chan bool)
go write(ch1)
go read(ch1,ch2)
<-ch2
}
下面是执行结果:
欢迎关注问我团队公众号:
有疑问加站长微信联系(非本文作者)