一、 关闭通道
发送者可以通过关闭信道,来通知接收方不会有更多的数据被发送到channel上。
close(ch)
接收者可以在接收来自通道的数据时使用额外的变量来检查通道是否已经关闭。
语法结构:
v, ok := <- ch
类似map操作,存储key,value键值对
v,ok := map[key] //根据key从map中获取value,如果key存在, v就是对应的数据,如果key不存在,v是默认值
在上面的语句中,如果ok的值是true,表示成功的从通道中读取了一个数据value。如果ok是false,这意味着我们正在从一个封闭的通道读取数据。从闭通道读取的值将是通道类型的零值。
例如,如果通道是一个int通道,那么从封闭通道接收的值将为0。
示例代码:
package main import ( "fmt" "time" ) func main() { ch1 := make(chan int) go sendData(ch1) /* 子goroutine,写出数据10个 每写一个,阻塞一次,主程序读取一次,解除阻塞 主goroutine:循环读 每次读取一个,堵塞一次,子程序,写出一个,解除阻塞 发送发,关闭通道的--->接收方,接收到的数据是该类型的零值,以及false */ //主程序中获取通道的数据 for{ time.Sleep(1*time.Second) v, ok := <- ch1 //其他goroutine,显示的调用close方法关闭通道。 if !ok{ fmt.Println("已经读取了所有的数据,", ok) break } fmt.Println("取出数据:",v, ok) } fmt.Println("main...over....") } func sendData(ch1 chan int) { // 发送方:10条数据 for i:=0;i<10 ;i++ { ch1 <- i//将i写入通道中 } close(ch1) //将ch1通道关闭了。 }
运行结果
在上面的程序中,send Goroutine将0到9写入chl通道,然后关闭通道。主函数里有一个无限循环。它检查通道是否在发送数据后,使用变量ok关闭。如果ok是假的,则意味着通道关闭,因此循环结束。还可以打印接收到的值和ok的值。
二、通道上的范围循环
我们可以循环从通道上获取数据,直到通道关闭。for循环的for range形式可用于从通道接收值,直到它关闭为止。
使用range循环,示例代码:
package main import ( "time" "fmt" ) func main() { ch1 :=make(chan int) go sendData(ch1) // for循环的for range形式可用于从通道接收值,直到它关闭为止。 for v := range ch1{ fmt.Println("读取数据:",v) } fmt.Println("main..over.....") } func sendData(ch1 chan int) { for i:=0;i<10 ; i++ { time.Sleep(1*time.Second) ch1 <- i } close(ch1)//通知对方,通道关闭 }
运行结果: