我在我的程序中发现了一个瓶颈,它是一个缓冲通道。我想给客户端一个系统负载的指示,这应该由通道中缓冲的消息数来指示。
Go 中有没有办法告诉通道中有多少缓冲消息?
如果您也有 Java 背景,我正在寻找类似的: http: //docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingQueue.html#size()
我在我的程序中发现了一个瓶颈,它是一个缓冲通道。我想给客户端一个系统负载的指示,这应该由通道中缓冲的消息数来指示。
Go 中有没有办法告诉通道中有多少缓冲消息?
如果您也有 Java 背景,我正在寻找类似的: http: //docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingQueue.html#size()
内置函数
len
并cap
接受各种类型的参数并返回 type 的结果int
。该实现保证结果始终适合int
.Call Argument type Result len(s) chan T number of elements queued in channel buffer cap(s) chan T channel buffer capacity
通道的len
函数给出了通道缓冲区中排队的元素的数量。例如,
package main
import "fmt"
func main() {
ch := make(chan int, 8)
ch <- 42
ch <- 7
<-ch
ch <- 64
// number of queued elements = 1 + 1 - 1 + 1 = 2
fmt.Println(len(ch), cap(ch))
}
输出:
2 8
有一个替代解决方案使用“队列”进程来处理消息的排队,并且还能够报告其大小。为此,您将需要一个输入通道和一个输出通道,以及一个用于获取大小的查询通道。因为会有两个输入通道,所以您需要在它们之间进行选择(CSP“选择”)。
这是一个运行中的小演示。队列由一个作为缓冲区的切片和一个输入通道组成。
func queue(in <-chan string, out chan<- string, query <-chan chan int) {
buffer := []string{}
var s string
var reply chan int
for {
// Go select doesn't support boolean guards so we need the 'if' outside the select instead
if len(buffer) > 0 {
select {
case reply = <-query:
reply <- len(buffer)
case s = <-in:
buffer = append(buffer, s)
case out <- buffer[0]:
buffer = buffer[1:]
}
} else {
select {
case reply = <-query:
reply <- len(buffer)
case s = <-in:
buffer = append(buffer, s)
}
}
}
}