缓冲通道
# 缓冲通道
# 一、非缓冲通道
前面的通道基本上都没有缓冲.发送和接收到一个未缓冲的通道都是阻塞的.
一次发送操作对应一次接收操作,对于一个goroutine
来讲,它的一次发送,在另一个goroutine
接收之前都是阻塞的.同样的,对于接收来讲,在另一个goroutine
发送之前,它也是阻塞的.
# 二、缓冲通道
缓冲通道就是指一个铜带,带有一个缓冲区.发送到一个缓冲通道只有在缓冲区满时才被阻塞.类似地,从缓冲通道接收的信息只有在缓冲区为空时才会被阻塞.
可以通过将额外的容量参数传递给make
函数来创建缓冲通道,该函数指定缓冲区的大小.
语法
ch := make(chan type,caacity)
1
上述语法的容量应该大于0
,以便通道有缓冲区.默认情况下,无缓冲通道的容量为0
,因此字啊之前创建通道时省略了容量参数.
# 三、示例代码
以下的代码中,chan
通道,是带有缓冲区的.
package main
import (
"fmt"
"strconv"
)
func main() {
/*
非缓冲通道: make(chan T)
一次发送,一次接收,都是阻塞的
缓冲通道: make(chan T,capacity)
发送: 缓冲区的数据满了,才阻塞
接收: 缓冲区的数据空了,才阻塞
*/
ch3 := make(chan int)
fmt.Println(len(ch3), cap(ch3)) //0,0
//ch3 <- 100 //阻塞式的,需要有其他的`goroutine`解除阻塞,否则deadlock
ch4 := make(chan int, 5) //缓冲通道,缓冲区大小5
fmt.Println(len(ch4), cap(ch4)) //0 5
ch4 <- 100
fmt.Println(len(ch4), cap(ch4)) //1 5
ch4 <- 200
ch4 <- 300
ch4 <- 400
ch4 <- 500
fmt.Println(len(ch4), cap(ch4))
fmt.Println("------------------------------")
ch5 := make(chan string, 4)
go sendData2(ch5)
for {
v, ok := <-ch5
if !ok {
fmt.Println("数据读取完了...", ok)
break
}
fmt.Println("\t读取的数据是: ", v)
}
fmt.Println("main...over...")
}
func sendData2(ch chan string) {
for i := 0; i < 10; i++ {
ch <- "数值" + strconv.Itoa(i)
fmt.Printf("子goroutine中写出数据: %d 个数据\n", i)
}
close(ch)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
执行结果
上次更新: 2024/04/09, 16:48:42
- 01
- AWS NAT-NetWork-Firwalld配置(一)04-09
- 02
- AWS NAT-NetWork-Firwalld配置(二)04-09
- 03
- kubernetes部署minio对象存储01-18