敞开chanel
发送者这边能够发送一个close(ch)
,接管方收到之后就晓得发送方之后都不会再发送信息了。
接收者这边能够通过一个额定的变量,检测通道是否曾经敞开。相似这样:v, ok := <- ch
这里的ok为false就代表咱们从一个曾经敞开的chanel获取数据,这个数据是chanel类型对应的零值。
例如:
package mainimport ( "fmt" "time")func main() { // 子协程:写10个数据,每写一次,就阻塞一次,主协程读取一次,阻塞解除一次 // 主协程:读取一次数据,阻塞一次,子协程写一次,阻塞解除一次 ch1 := make(chan int) go sendData(ch1) //读取chanel中的数据,不过因为咱们可能不晓得发送方发送了多少数据, 这里用死循环 for { time.Sleep(1 * time.Second) v, ok := <-ch1 if !ok { fmt.Println("all the data has bean read ", ok) break } fmt.Println("the data read is: ", v, ok) }}func sendData(ch1 chan int) { // 发送方: 发送10条数据 for i := 0; i < 10; i++ { //把i写入chanel ch1 <- i } //敞开ch1通道 close(ch1)}
运行后果是:
the data read is: 0 truethe data read is: 1 truethe data read is: 2 truethe data read is: 3 truethe data read is: 4 truethe data read is: 5 truethe data read is: 6 truethe data read is: 7 truethe data read is: 8 truethe data read is: 9 trueall the data has bean read false
chanel的range循环
绝对于下面的for 用range可能省去对ok值的判断,更加简洁不便地操作chanel。
上面这个例子中,range的含意就是从通道ch1中读取数据并且赋值给v:
package mainimport ( "fmt" "time")func main() { // 子协程:写10个数据,每写一次,就阻塞一次,主协程读取一次,阻塞解除一次 // 主协程:读取一次数据,阻塞一次,子协程写一次,阻塞解除一次 ch1 := make(chan int) go sendData(ch1) //读取chanel中的数据,不过因为咱们可能不晓得发送方发送了多少数据, 这里用死循环 for v := range ch1 { //这里range的含意就是从通道ch1中读取数据并且赋值给v [v<- ch1] fmt.Println("reading data: ", v) } fmt.Println("main-goroutine completed")}func sendData(ch1 chan int) { // 发送方: 发送10条数据 for i := 0; i < 10; i++ { time.Sleep(1 * time.Second) //把i写入chanel ch1 <- i } //敞开ch1通道 close(ch1)}
运行后果是:
reading data: 0reading data: 1reading data: 2reading data: 3reading data: 4reading data: 5reading data: 6reading data: 7reading data: 8reading data: 9main-goroutine completed