代码清单9-8展示了两个以goroutine形式独立运行的函数,其中一个函数是投掷器(thrower),它接受一个通道作为参数,然后一个接一个地把一组数字发送到通道里;而另一个函数则是捕捉器(catcher),它会从相同的通道里一个接一个地取出一组数字,并把这些数字打印出来。
代码清单9-8 使用通道实现消息传递
package main
import (
"fmt"
"time"
)
func thrower(c chan int) {
for i := 0; i < 5; i++ {
c <- i//把数字值推入通道中
fmt.Println("Threw >>", i)
}
}
func catcher(c chan int) {
for i := 0; i < 5; i++ {
num := <-c//从通道中取出数字值
fmt.Println("Caught <<", num)
}
}
func main() {
c := make(chan int)
go thrower(c)
go catcher(c)
time.Sleep(100 * time.Millisecond)
}
运行这个程序将得到以下结果:
Caught << 0
Threw >> 0
Threw >> 1
Caught << 1
Caught << 2
Threw >> 2
Threw >> 3
Caught << 3
Caught << 4
Threw >> 4
在这段输出结果中,某些Caught语句出现在了Threw语句的前面,但这并不意味着程序的运行出现了错误——之所以会出现这样的乱象,仅仅是因为运行时环境在向通道推入值或者从通道中取出值之后,调度到了打印语句所致。最重要的是,打印语句中出现的数字都是有序的,这意味着投掷器在向通道“投掷”一个数字之后,捕捉器必须先“捕捉”这个数字,然后才能处理下一个数字。