数据接受者总是面临这样的问题:何时停止等待数据?还会有更多的数据么,还是所有内容都完成了?我应该继续等待还是该做别的了?
对于该问题,一个可选的方式是,持续的访问数据源并检查channel是否已经关闭,但是这并不是高效的解决方式。Go提供了range
关键字,将其使用在channel上时,会自动等待channel的动作一直到channel被关闭
-
示例代码1
-
package main
-
import (
-
"fmt"
-
"time"
-
"strconv"
-
)
-
func makeCakeAndSend(cs chan string, count int) {
-
for i := 1; i <= count; i++ {
-
cakeName := "Strawberry Cake " + strconv.Itoa(i)
-
cs <- cakeName //send a strawberry cake
-
}
-
}
-
func receiveCakeAndPack(cs chan string) {
-
for s := range cs {
-
fmt.Println("Packing received cake: ", s)
-
}
-
}
-
func main() {
-
cs := make(chan string)
-
go makeCakeAndSend(cs, 5)
-
go receiveCakeAndPack(cs)
-
//sleep for a while so that the program doesn’t exit immediately
-
time.Sleep(3 * 1e9)
-
}
-
输出结果
-
Packing received cake: Strawberry Cake 1
-
Packing received cake: Strawberry Cake 2
-
Packing received cake: Strawberry Cake 3
-
Packing received cake: Strawberry Cake 4
-
Packing received cake: Strawberry Cake 5
我们告诉了蛋糕制作器我们需要5个蛋糕,但是蛋糕装箱器并不知道数目,而在之前版本的代码中,我们写死了具体的接收数目。上面的代码中,通过对channel使用range
关键字,我们避免了给接收者写明要接收的数据个数这种不合理的需求——当channel被关闭时,接收者的for
循环也被自动停止了
Channel and select
select
关键字用于多个channel的结合,这些channel会通过类似于are-you-ready polling的机制来工作。select
中会有case
代码块,用于发送或接收数据——不论通过<-</