Golang – Channel Unbuffered VS Buffered区别

参考文章:


在Go中我们make一个channel有两种方式,分别是有缓冲的 (buffered) 和没缓冲的 (unbuffered)

  • Buffered channel 创建方式为 make(chan TYPE,SIZE)
    – 如:make(chan string,2) 就是创建一个string类型,buffer大小为3的channel
  • Unbuffered channel创建方式为 make(chan TYPE)
    – 如: make(chan string) 就是创建一个string 类型的channel,无需定义buffer大小

Unbuffered 和 buffered channel的区别

  • Unbuffered channel是channel发送和接收是同时发生的
    – 如: ch := make(chan int) 如果没goroutine 读取接收者 <-ch 那么发送者 ch<- 就会一直塞着
  • Buffered channel 只有列队满了才可能发生阻塞

Unbuffered Channel的代码案例

  • 同步进行的,在读取channel会阻塞,直到goroutine当中发送数据到channel
func main() {
	ch := make(chan int)

	go func() {
		ch <- 42 // 发送操作
		fmt.Println("Sent value")
	}()

	value := <-ch // 接收操作
	fmt.Println("Received value:", value)
}
  • 以下是unbuffered channel,loop着接收来自channel的数据
  • 由于是同步进行的,所以必须一进就一出,如果读取的部分慢了,那么写入的部分就会卡着等待了
func main() {
	ch := make(chan int)

	// 启动一个 goroutine 来发送数据
	go func() {
		for i := 0; i < 5; i++ { // 循环发送5次数据
			ch <- i
			fmt.Println("Sent value:", i)
			time.Sleep(time.Second) // 睡眠1秒,模拟一些工作
		}
		close(ch) // 发送完成后关闭通道
	}()

	// 主 goroutine 接收数据
	for value := range ch {
		fmt.Println("Received value:", value)
	}
}

Buffered Channel的代码案例

  • 都是异步处理的,不会因为读取的数据慢了而阻塞
  • 如果channel满了,就会阻塞,必须等待channel腾出空位了之后才能继续往内发送数据
func main() {
	ch := make(chan int, 2) // 创建一个容量为 2 的缓冲通道

	ch <- 1 // 发送操作,不会阻塞
	fmt.Println("Sent value 1")

	ch <- 2 // 发送操作,不会阻塞
	fmt.Println("Sent value 2")

	go func() {
		ch <- 3 // 发送操作,此时会阻塞,直到有空位
		fmt.Println("Sent value 3")
	}()

	value1 := <-ch // 接收操作
	fmt.Println("Received value:", value1)

	value2 := <-ch // 接收操作
	fmt.Println("Received value:", value2)

	value3 := <-ch // 接收操作,解除阻塞
	fmt.Println("Received value:", value3)
}
输出结果:
Sent value 1
Sent value 2
Received value: 1
Received value: 2
Sent value 3
Received value: 3

Loading

Facebook评论