上篇我们了解到了goroution和channel的基础概念,在这个过程中我们通过实例讲解了channel这个媒介如何实现在不同的channel中传递数据。当然了在过程中我们遇到了因为死锁造成的dealock,随之引出了channel的缓冲这个概念……
今天我们就书接上回,通过一个实例来讲解channel的缓冲区和单方向的channel。停车场是作为讲解缓冲区的最好例子---车位数量就好比是缓冲区的容量(cap),当前已经停泊的车就是len,而停车和取车对应channel的数据发送和数据接收。
我们先模拟取车
func leave(leave chan Bus) {
if len(leave) == 0 {
fmt.Println("station为空")
return
}
fmt.Println("离开")
<-leave
}
下面是模拟的停车
func enter(enter chan Bus) {
if len(enter) == cap(enter) {
fmt.Println("车位已满…")
return
}
fmt.Println("停车")
enter <- 1
}
上面的leave和enter逻辑十分简单---车位被沾满时无法进入停车场,只有当有空闲车位才能进入泊车。接着我们看看如何简单的模拟随机停车和取车以及如何打烊时清空车场
func main() {
station := make(chan Bus, 5)//停车位5 代表缓冲区大小为0
dayTime := 10
for true && dayTime > 0 {
time.Sleep(time.Second)
switch rand.Int() % 2 {
case 0:
go enter(station)
break
case 1:
go leave(station)
}
dayTime -= 1
}
time.Sleep(time.Second)
fmt.Println("停车场准备打烊:", len(station))
close(station) //关闭停车通道
for range station {
fmt.Println("离开")
}
fmt.Println("over")
}
我们简单的说明一下我们的模拟逻辑:
1 构建一个小型的缓冲区为5的station
2 使用随机产生0 1代表停车和取车来进行channel发送和接受数据
3进行10测试,然后结束进行缓冲区清理(也许此时的缓冲区已经为0),通过close关闭channel,这时只能从缓冲区取数据而不能再向缓冲区发送数据
4 使用range来不停的从已经关闭的channel缓冲区取数
单方向channel
我们都知道通常停车场都是一杆一车进口和出口都是单向的,当然了老式的车长还是很多出口即入口。生活中我们还看到很多这样单向的粒子:4车单向车道等等…那么我们的channel呢?当然也是有的只是默认情况是双向通道而已
a:=make(chan <- int)
b:=make(<-chan int)
上例中我们分别声明只能发送数据和接受数据的单向channel,下面我们就看看怎么将我们上文中停车和取车的函数修改为单向的
func enter(enter chan<- Bus) {
if len(enter) == cap(enter) {
fmt.Println("车位已满…")
return
}
fmt.Println("停车")
enter <- 1
}
func leave(leave <-chan Bus) {
if len(leave) == 0 {
fmt.Println("station为空")
return
}
fmt.Println("离开")
<-leave
}
简单的总结一下:
我们引入了channel的缓冲区,根据不同的场景需求使用了单向的channel,然后接触到了time.Sleep和使用range怎么遍历等待一个channle