一、缓冲channel创建
// 给make函数,传递第2个参数,指定缓冲队列大小
ch := make(chan int, 100)
缓冲channel的使用方式跟无缓冲channel一样,区别就是往channel写输入数据的时候,如果缓存队列还没满,是不会阻塞写操作,例如:上面创建了的channel缓冲队列大小是100,如果写入到channel中,还未被取走的数据大于100,就会阻塞写操作。
二、缓冲channel应用示例
1.示例1
package main
import (
"fmt"
)
// 定义计算斐波拉契数列的函数,通过channel参数c返回每一步的计算结果
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i := 0; i < n; i++ {
// 返回当前计算结果
c <- x
x, y = y, x+y
}
// 通过close关闭channel
close(c)
}
func main() {
// 定义int类型的channel,缓冲队列大小是10
c := make(chan int, 10)
// 创建一个协程,开始计算数列
go fibonacci(10, c)
// 通过range关键词,循环遍历channel变量c,从c中读取数据
// 如果channel没有数据,就阻塞循环,直到channel中有数据
// 如果channel关闭,则退出循环
for i := range c {
fmt.Println(i)
}
}
运行结果如下:
0
1
1
2
3
5
8
13
21
34
2.示例2
package main
import (
"fmt"
"time"
)
func BufChannel() {
//创建一个有缓存的channel
ch := make(chan int, 3) //容量是3
//len(ch)缓冲区剩余数据个数, cap(ch)缓冲区大小
fmt.Printf("缓冲区剩余数据个数:%d, 缓冲区大小:%d\n", len(ch), cap(ch))
//新建协程
go func() {
for i := 1; i <= 10; i++ { //这里数据量大于管道容量,会出阻塞
fmt.Printf("子协程[%d]开始写入: 缓冲区剩余数据个数:%d, 缓冲区大小:%d\n", i, len(ch), cap(ch))
ch <- i //往chan写内容,如果主协程没读的话,写满3个就会阻塞在此
}
}()
//延时
fmt.Printf("我要去睡5秒\n")
time.Sleep(5 * time.Second)
fmt.Printf("睡醒了\n")
for i := 1; i <= 10; i++ { //这里数据量大于管道容量,会出阻塞
fmt.Printf("子协程[%d]准备读出: 缓冲区剩余数据个数:%d, 缓冲区大小:%d\n", i, len(ch), cap(ch))
num := <-ch //读管道中内容,没有内容前,阻塞
fmt.Printf("子协程[%d]已读,读出结果为[%d]: 缓冲区剩余数据个数:%d, 缓冲区大小:%d\n", i, num, len(ch), cap(ch))
}
}
func main() {
// 有缓冲通道
BufChannel()
}
运行结果
缓冲区剩余数据个数:0, 缓冲区大小:3
我要去睡5秒
子协程[1]开始写入: 缓冲区剩余数据个数:0, 缓冲区大小:3
子协程[2]开始写入: 缓冲区剩余数据个数:1, 缓冲区大小:3
子协程[3]开始写入: 缓冲区剩余数据个数:2, 缓冲区大小:3
子协程[4]开始写入: 缓冲区剩余数据个数:3, 缓冲区大小:3
睡醒了
子协程[1]准备读出: 缓冲区剩余数据个数:3, 缓冲区大小:3
子协程[1]已读,读出结果为[1]: 缓冲区剩余数据个数:3, 缓冲区大小:3
子协程[2]准备读出: 缓冲区剩余数据个数:3, 缓冲区大小:3
子协程[2]已读,读出结果为[2]: 缓冲区剩余数据个数:2, 缓冲区大小:3
子协程[3]准备读出: 缓冲区剩余数据个数:2, 缓冲区大小:3
子协程[3]已读,读出结果为[3]: 缓冲区剩余数据个数:1, 缓冲区大小:3
子协程[4]准备读出: 缓冲区剩余数据个数:1, 缓冲区大小:3
子协程[4]已读,读出结果为[4]: 缓冲区剩余数据个数:0, 缓冲区大小:3
子协程[5]准备读出: 缓冲区剩余数据个数:0, 缓冲区大小:3
子协程[5]开始写入: 缓冲区剩余数据个数:3, 缓冲区大小:3
子协程[6]开始写入: 缓冲区剩余数据个数:0, 缓冲区大小:3
子协程[7]开始写入: 缓冲区剩余数据个数:1, 缓冲区大小:3
子协程[8]开始写入: 缓冲区剩余数据个数:2, 缓冲区大小:3
子协程[9]开始写入: 缓冲区剩余数据个数:3, 缓冲区大小:3
子协程[5]已读,读出结果为[5]: 缓冲区剩余数据个数:2, 缓冲区大小:3
子协程[6]准备读出: 缓冲区剩余数据个数:3, 缓冲区大小:3
子协程[6]已读,读出结果为[6]: 缓冲区剩余数据个数:3, 缓冲区大小:3
子协程[7]准备读出: 缓冲区剩余数据个数:3, 缓冲区大小:3
子协程[7]已读,读出结果为[7]: 缓冲区剩余数据个数:2, 缓冲区大小:3
子协程[8]准备读出: 缓冲区剩余数据个数:2, 缓冲区大小:3
子协程[8]已读,读出结果为[8]: 缓冲区剩余数据个数:1, 缓冲区大小:3
子协程[9]准备读出: 缓冲区剩余数据个数:1, 缓冲区大小:3
子协程[9]已读,读出结果为[9]: 缓冲区剩余数据个数:0, 缓冲区大小:3
子协程[10]准备读出: 缓冲区剩余数据个数:0, 缓冲区大小:3
子协程[10]开始写入: 缓冲区剩余数据个数:0, 缓冲区大小:3
子协程[10]已读,读出结果为[10]: 缓冲区剩余数据个数:0, 缓冲区大小:3