Go之读取已有的缓存chan数据

有一个并发的 Go 协程来向chan写入数据,而 Go 主协程负责读取(接收)数据。

Go 主协程中创建了容量为 100 的chan队列 ch,而第 25 行把 ch 传递给了 write 协程。接下来 Go 主协程休眠了2秒。
在这期间,write 协程在并发地运行。write 协程有一个 for 循环,依次向chan队列 ch 写入 0~47,然后休眠0.3秒。而缓冲chan的容量为 100,如果写满100,则发生阻塞,直到 ch 内的值被读取。

读取操作每次读取前先判断缓存chan队列ch中缓存的元素数量。
如果没有缓冲元素则休眠0.2秒。
如果有缓冲元素,则判断缓冲元素个数len(ch)是否大于MAXREQLEN (30)。如果len(ch)>30,则一个批次读取30个元素,否则一个批次读取len(ch)个元素。
读取到元素后,do some thing,然后继续读取。

package main

import (
	"fmt"
	"time"
)

var MAXREQLEN = 30

func write(ch chan int) {
	for {
		for i := 0; i < 47; i++ {
			ch <- i
			fmt.Println("successfully wrote", i, "to ch")
		}
		time.Sleep(300 * time.Millisecond)
	}

	//close(ch)
}
func main() {
	//test()

	ch := make(chan int, 100)
	go write(ch)
	time.Sleep(2 * time.Second)

	for {
		numArr := make([]int, 0)
		bufferChan := len(ch)
		if bufferChan > 0 {
			var max int
			if bufferChan > MAXREQLEN {
				max = MAXREQLEN
			} else {
				max = bufferChan
			}
			for i := 0; i < max; i++ {
				v := <-ch
				fmt.Println("read value", v, "from ch")
				numArr = append(numArr, v)
			}
			fmt.Println(numArr)
			fmt.Println("do some thing")
		}
		time.Sleep(200 * time.Millisecond)
		fmt.Println("Sleep(100 * time.Millisecond)")
	}

}

func test() {
	c := make(chan int, 100)

	fmt.Println("1.len:", len(c))

	for i := 0; i < 34; i++ {
		c <- 0
	}

	fmt.Println("2.len:", len(c))

	<-c

	<-c

	fmt.Println("3.len:", len(c))
}

 

发送者可通过 close 关闭一个信道来表示没有需要发送的值了。接收者可以通过为接收表达式分配第二个参数来测试信道是否被关闭:若没有值可以接收且信道已被关闭,那么在执行完

v, ok := <-ch

之后 ok 会被设置为 false

循环 for i := range c 会不断从信道接收值,直到它被关闭。

*注意:* 只有发送者才能关闭信道,而接收者不能。向一个已经关闭的信道发送数据会引发程序恐慌(panic)。

*还要注意:* 信道与文件不同,通常情况下无需关闭它们。只有在必须告诉接收者不再有需要发送的值时才有必要关闭,例如终止一个 range 循环。

package main

import (
	"fmt"
)

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(c)
}

func main() {
	c := make(chan int, 10)
	go fibonacci(cap(c), c)
	for i := range c {
		fmt.Println(i)
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值