6

关闭chanel

发送者这边可以发送一个close(ch),接收方收到之后就知道发送方之后都不会再发送信息了。
接收者这边可以通过一个额外的变量,检测通道是否已经关闭。类似这样:v, ok := <- ch这里的ok为false就代表我们从一个已经关闭的chanel获取数据,这个数据是chanel类型对应的零值。

例如:

package main

import (
    "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 true
the data read is:  1 true
the data read is:  2 true
the data read is:  3 true
the data read is:  4 true
the data read is:  5 true
the data read is:  6 true
the data read is:  7 true
the data read is:  8 true
the data read is:  9 true
all the data has bean read  false

chanel的range循环

相对于上面的for 用range能够省去对ok值的判断,更加简洁方便地操作chanel。

下面这个例子中,range的含义就是从通道ch1中读取数据并且赋值给v:

package main

import (
    "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:  0
reading data:  1
reading data:  2
reading data:  3
reading data:  4
reading data:  5
reading data:  6
reading data:  7
reading data:  8
reading data:  9
main-goroutine completed

LiberHome
409 声望1.1k 粉丝

有问题 欢迎发邮件 📩 liberhome@163.com