Go微服务实战
上QQ阅读APP看书,第一时间看更新

5.2.2 channel接收数据

在了解了如何向channel写入数据后,下面来看如何从channel处接收数据。上一节向channel写入数据时使用的是c<-,而从channel读取数据则正好反过来,使用的是<-c。

还是通过示例代码来看一下:


book/ch05/5.2/read/main.go
1. package main
2.
3. import (
4.     "fmt"
5.     "time"
6. )
7.
8. func main() {
9.      c := make(chan int)
10.     go writeChan(c,666)
11.     time.Sleep(1*time.Second)
12.     fmt.Println("Read:",<-c)
13.     if _,ok := <-c;ok{
14.         fmt.Println("Channel is Open")
15.     }else {
16.         fmt.Println("Channel is closed")
17.     }
18. }
19.
20. func writeChan(c chan int,x int)  {
21.     fmt.Println("Start:",x)
22.     c <- x
23.     close(c)
24.     fmt.Println("End:",x)
25. }

第20行至第25行,像读取channel的例子一样,也写了writeChan函数,毕竟要测试读,首先要写。

第9行至第11行,也和上一个示例代码一样,定义一个channel,然后传入writeChan函数,并启动一个goroutine来运行这个函数,并且在第11行让主goroutine休眠。

第12行至第17行是这个示例和上一个示例的不同之处。在第12行,先使用<-c读取了通道c的数据,第13行至第17行则是再次读取c,并查看通道c是否被关闭。上一示例有相应解释,一旦写入数据通道就会阻塞,而被读取之后就会继续,正好下一行就是第23行关闭通道。

多运行几次,结果大多如下:


Start: 666
Read: 666
End: 666
Channel is closed

不过也出现了如下这种情况:


Start: 666
Read: 666
Channel is closed

这是因为主goroutine关闭的时候,writeChan函数的goroutine还没来得及执行第24行,可见这样写还是不够严谨。

注意

通过close函数关闭channel不是必须的,只有在需要通知其他的数据读取通道数据已经写入完成时,才必须关闭。不主动关闭的通道,垃圾回收器会自动回收。而文件操作的close函数则是必须有的,请读者区分开。