go学习笔记_Routine和Channel下

go语言并发编程下

上文从基础层面讲解了goroutinechannel ,关于如何使用都停留下嘴皮子上,因此下篇选用几个最简单的例子来巩固下。另外推荐下自己的个人博客,你可以先点进行看下内容是否对您有帮助,在选择收藏或者直接x掉。

个人博客地址:Colourful Code

正文

首先,上文说到channel 有两种情况:

  • 未分配缓存

  • 分配一定缓存

例子从这两点入手给出。

未分配缓存

package main
import "fmt"
//求和函数sum
func sum(a []int,c chan int){
    sum :=0
    for _,v := range a{
        sum += v
    }
    c<-sum          //向通道c 写入数据值 sum
}
//主程序入口
func main(){
    a:= []int{1,3,5,2,-2}
    c:= make(chan int)
    go sum(a[:],c)      //开辟一个goroutine 用于进行sum函数执行
    x:= <-c             //读取c通道的值赋值给x
    fmt.Println(x)
}

从主程序开始分析,如下分为几个步骤:

  • 声明定义了一个数组 a

  • 声明定义了一个通道 c,注意是没有给定缓存的。

  • 正因为加了go关键字 ,所以为sum函数开辟一个goroutine,同时给函数传入参数:数组a和通道c。这个时候程序除了主routine,也就是main函数。与此同时还有为sum开辟的子routine,这个子routine所要做的就是对传入的数组进行求和,并且将结果值写入通道c中。

  • routine执行完go sum(a[:],c)这条语句之后,马上就可以执行下一条语句了。也就是 x:=<-c。 这里就有点意思了。要根据实际情况分2种情况来说:c 通道有值和无值。

    1. c 通道有值,这意味着子goroutine 中进行的求和运算先完成,通过语句c<-sum 将结果值写入通道时,由于完成的太早,没有接收方从通道读取数据造成了堵塞,子routine中的程序卡死在这里,等待接收者读取数据。直到主routine执行了x:=<-c这条语句,顺利的从通道读取到了数据,于此同时子routinec<-sum 由于通道数据被读走,这里不再堵塞,子routine中的sum函数执行完毕。
    2. c 通道没有值,意味着子goroutine 中进行的求和运算还未完成(假如这里的求和运算改为大数据处理,我想要花费很多时间。),数据还未写入到c通道中,因此由于通道内没有数据,主routine中会堵塞在 x:=<-c这条语句上,等待子routine完成数据计算,执行c<-sum语句往通道中写数据。这时候主routine中 顺利读取通道c中的值,赋值给x,打印出来。

分配缓存

package main
import "fmt"
func main(){
    c:=make(chan int,2)
    c <- 10
    c <- 20
    fmt.Println(<-c)
    fmt.Println(<-c)
}

由于理解了channel 工作机制,那么分配缓存理解起来容易一些。

  • 首先声明定义一个缓存大小为2的特定类型为int的通道c

  • 往通道写入值10,想一想,倘若没有分配缓存,那么程序会堵塞在这里,除非其他routine会从该通道读取数据,但这显然不可能,因为这时候是在主routine中,你又没有创建子routine,所以最后只会报错,“all goroutines are asleep - deadlock!”

  • 这时候你应该已经理解了,正因为分配了缓存,因此能够顺利的写入值10,接下来往通道写入值20,显然由于缓存还有空间,写入没有问题,不会造成堵塞,程序继续执行下去!

  • <-c就是从通道中读取数据,会打印10

  • 打印20,有种FIFO(注:“first in first out”,先入先出)的感觉,由于我们往通道缓存中写入值10,再写入值20,取出时就应该有顺序的先取出值10,再取出值20。

结尾:

博主是一个刚入坑的go小菜鸟,对go语言理解可能还不是很透彻,倘若哪里理解不对,或者写的有问题,欢迎指正,踩踩更健康嘛,不过希望您能留言告诉我为啥踩的理由吗,好让我改正,这也算一种学习不是吗?最后谢谢!

发布了75 篇原创文章 · 获赞 70 · 访问量 10万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章