关于通道缓存
关于通道缓存,为了方便理解我暂时可理解为通道的数组,特性慢慢分析下
先学习通道的关闭
通道关闭,意味着不能在往通道发数据了.但是还可以接收数据.
package main
import "fmt"
func main() {
jobs := make(chan int, 5)
done := make(chan bool)
go func() {
for {
j, more := <-jobs
//more在通道已经关闭并且所有的信息都已经被接受情况下为false
if more {
fmt.Println("完成工作:", j)
} else {
fmt.Println("工作全部完成")
done <- true
return
}
}
}()
for j := 1; j <= 3; j++ {
jobs <- j
fmt.Println("布置工作:", j)
}
close(jobs)
fmt.Println("关闭通道")
// <-done这里是之前单通道的特性,用于等待协程完工,否则程序直接结束了
<-done
}
/*打印的结果为
布置工作: 1
布置工作: 2
布置工作: 3
关闭通道
完成工作: 1
完成工作: 2
完成工作: 3
工作全部完成
为了更直观的分析 关闭通道我们这么来进行测试
package main
import (
"fmt"
"time"
)
func main() {
jobs := make(chan int, 5)
go func() {
for {
fmt.Println("接收方协程开始工作:")
j := <-jobs
time.Sleep(time.Second*1)
fmt.Println("完成工作:", j)
}
}()
time.Sleep(time.Second*3)
for j := 1; j <= 3; j++ {
jobs <- j
fmt.Println("布置工作:", j)
}
close(jobs)
fmt.Println("完成工作并关闭通道,")
time.Sleep(time.Second*20)
/*
接收方协程开始工作:
布置工作: 1
布置工作: 2
布置工作: 3
完成工作并关闭通道,
完成工作: 1
接收方协程开始工作:
完成工作: 2
接收方协程开始工作:
完成工作: 3
接收方协程开始工作:
完成工作: 0
接收方协程开始工作:
完成工作: 0
...
}
一旦关闭通道接收方没处理的话会无限循环下去.
遍历通道
package main
import (
"fmt"
"time"
)
func main() {
queue := make(chan string, 2)
go func() {
for elem := range queue {
fmt.Println(elem)
}
fmt.Println("完成了下一步")
}()
queue <- "one"
queue <- "two"
//close(queue)
time.Sleep(time.Second*2)
queue <- "111"
close(queue)
time.Sleep(time.Second*10)
/*如果将close(queue) 注释掉 那么协程将会继续阻塞到接受第四个值
}
这个例子如果使用 elem:=<- queue 来接受数据的话
那么我们能输入进通道的数据 就是缓存数+ <- queue 的个数 否则就要报错
range就相当于在接收方就相当于无限,发送方可以无限发送数据