Golang学习笔记(二十):深入学习Channel

https://juejin.im/post/5c962f44f265da60e17d00bd






《Golang学习笔记(十九):Channel初步接触》小节中已经学习了channel的一些基础概念了,总结一下大概是以下几点:

  1. channel是Go语言中gotoutine之间数据通讯的机制。
  2. 可以使用内置函数make()初始化channel类型。
  3. 使用close()函数关闭channel关闭后,不能再往channel发送信息。

好了,简单复习了一下,下面开始深入的学习吧。

channel的分类

同步channel

当我们使用make()函数创建一下channel类型时,如下代码所示:

  1. ch := make(chan int)

此时所创建的channel只能往里面发送一个元素,如果元素没有被另一个gotoutine接收,继续向channel发送元素的gotoutine便会阻塞,这种只能发送单个元素的channel,称为无缓存channel,也称为同步channel,可用于不同goroutine之间的数据同步操作。

  1. package main
  2. import "fmt"
  3. func main() {
  4. ch1 := make(chan int)
  5. ch2 := make(chan int)
  6. // 计数
  7. go counter(ch1)
  8. // 求平方
  9. go squarer(ch1,ch2)
  10. // 在主goroutine中打印同步过来的数据
  11. for x := range ch2 {
  12. fmt.Println(x)
  13. }
  14. }
  15. func counter(ch chan int) {
  16. for x := 0; x < 1000; x++ {
  17. ch <- x
  18. }
  19. close(ch)
  20. }
  21. func squarer(ch1,ch2 chan int){
  22. for x := range ch1 {
  23. ch2 <- x * x
  24. }
  25. close(ch2)
  26. }

在上面的例子中,我们创建了两个goroutine,在counter goroutine产生数值,并同步到另一个squarer goroutine,而squarer goroutine则将元素同步到main goroutine当中,最后再打印输出。

这就是无缓存区的channel的作用,串联不同的goroutine,来达到数据同步的目的。

异步channel

如果想创建一个带缓存区的channel类型,可以使用make()函数的第二个参数来指定channel的队列容量,如:

  1. ch := make(chan int,3)

通过这种创建的channel,也称为异步channel,底层数据结构为一个指定长度元素队列,这里的长度为3,当向channel发送数值时,如果队列未满,则不会发生阻塞,元素会添加在队列的末尾,而接收的goroutine则从队列的头部读取元素。

所以,根据channel是否有缓存区,可将channel分为同步channel异步channel

channel的方向性

在上面的例子中,我们看到squarer goroutinech1的操作只是读取元素,而对ch2操作只是发送元素,在counter goroutinech1的也只是发送元素。

如果从操作的方向性来讲的话,channel可分为只用于发送和只用于接收,也就是单方向channel,定义的方式如下所示:

  1. var ch chan int //可以发送和接收的普通channel
  2. var in <-chan int //只能发送操作的channel
  3. var out chan<- int //只能接收操作的channel

当向用于接收的channel发送元素和从只能用于发送元素的channel接收元素时,都会引发错误。

另外,使用close()函数关闭只能用于接收的channel时,也会引发错误,因为只有发送端才能关闭。

因此,我们可以将上面的例子中两个函数的形参修改为:

  1. func counter(ch chan<- int) {
  2. ...//省略函数体
  3. }
  4. func squarer(ch1 <-chan int,ch2 chan<- int){
  5. ...//省略函数体
  6. }
ft_authoradmin  ft_create_time2019-08-03 17:10
 ft_update_time2019-08-03 17:10