带你撸出一手好代码
Golang Channel 类型浅谈

golang 的 channel其实是一个阻塞队列,实现了生产者和消费者模式, 通常用于线程之间的通信。

 

make一个channel的时候可以传递两个参数,第一个是channel的类型,第二个是可选参数, 指定队列的长度。

 

我们重点讲讲这第二个参数的作用。

 

当不指定第二个参数时,如这样创建channal

 

var channel = make(chan int)



那么这个队列的长度为0, 不能往里面存东西,如过生产端想往里面放东西,前提条件是接受端必须已经处于接受状态,如果接收端还没有处于读取状态,那么生产端就会被阻塞

 

var channel = make(chan string)
go func() {
    channel <- "step1"
    fmt.Println("step2")
}()
time.Sleep(time.Second * 1)
var val = <- channel
fmt.Println(val)
 
for true {;}


 如上面这段代码

 

新开的线程中这一句

 

channel <- "step1"


 会在主线程

 

var val = <- channel


 这一句之后执行。

 

这就好比快递员送快递,必需等到顾客收货签字后才能继续为下一个顾客服务,如果顾客来的晚了, 那么快递员的时间会被浪费掉,在原地瞎等。

 

如果创建channel的时候指定第二个参数, 那么这个channel就是一个有长度的队列, 只要里面没有被填满,生产端就一直可以往里面塞东西,程序的执行不会被阻塞。如果队列满了,而接受端又没及时去除队列中的元素, 此时生产端才会被阻塞,就像之前讲的长度为0的队列一样。

 

var channel = make(chan string,1)
go func() {
    channel <- "step1"
    fmt.Println("step2")
}()
time.Sleep(time.Second * 1)
var val = <- channel
fmt.Println(val)
 
for true {;}


 此代码为上一个例子代码的拷贝,不同之处是指定的make channel的第二个参数,此时

 

channel <- "step1"


 这句代码的执行并不用等待

 

var val = <- channel


 新开的线程中

 

"step2"

 

这个值会被迅速打印

 

在拿之前送快递的例子讲,指定了第二个参数的channel就像一个蜂巢快递柜, 快递员只要将快递放到里面,让顾客自己来取,然后管自己去送下一个快递,如此当需要送的快递数量多时, 变可以节省时间, 增加效率。 当然,如果蜂巢柜装满了,那么快递员必须等到有顾客来那走柜中快递, 腾出空间, 快递员才可以继续往里面装快递,否者还是得等,这和channel的机制一样。

 

总而言之,channel其实就是一个阻塞队列,这在java或者c#中都有,没啥稀奇的。

作者:陈大侠
日期:2018-04-28

留言(0条)

我要发表留言

您的大名 选填
电子邮箱 选填

欢迎关注微信公众号 「带你撸出一手好代码」

首页    GitHub 知乎 豆瓣 博客园