敞开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