英文:
Is there a way to tell how many messages are in channel buffer?
问题
我在我的程序中发现了一个瓶颈,它是一个缓冲通道。我想给客户端一个系统负载的指示,这应该由通道中缓冲的消息数量来表示。
在Go语言中有没有办法告诉有多少个缓冲消息在通道中?
如果你也有Java背景,我正在寻找一个类似于这个的等价物:http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingQueue.html#size()
英文:
I have identified a bottleneck in my program, it is a buffered channel. I would like to give client an indication of system load, which should be indicated by number of messages buffered in the channel.
Is there a way in Go to tell how many buffered messages there are in a channel?
If you also have a Java background, I am looking for an equivelent of this: http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingQueue.html#size()
答案1
得分: 18
len
和cap
是内置函数,它们接受不同类型的参数,并返回int
类型的结果。实现保证结果始终适合int
类型。
len(s)
函数用于通道,返回通道缓冲区中排队的元素数量。
cap(s)
函数用于通道,返回通道缓冲区的容量。
通道的len
函数返回通道缓冲区中排队的元素数量。例如,
package main
import "fmt"
func main() {
ch := make(chan int, 8)
ch <- 42
ch <- 7
<-ch
ch <- 64
// 排队的元素数量 = 1 + 1 - 1 + 1 = 2
fmt.Println(len(ch), cap(ch))
}
输出:
2 8
英文:
> Length and capacity
>
> The built-in functions len
and cap
take arguments of various types
> and return a result of type int
. The implementation guarantees that
> the result always fits into an int
.
>
> Call Argument type Result
>
> len(s) chan T number of elements queued in channel buffer
>
> cap(s) chan T channel buffer capacity
The len
function for a channel gives the number of elements queued in the channel buffer. For example,
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))
}
Output:
2 8
答案2
得分: -2
这里有一个替代方案,使用一个“队列”进程来处理消息的排队,并且能够报告其大小。为此,您将需要一个输入通道和一个输出通道,以及一个查询通道来获取大小。因为会有两个输入通道,所以您需要在它们之间使用选择(CSP的“选择”)。
这是一个小演示。队列由一个切片作为缓冲区和一个输入通道组成。
func queue(in <-chan string, out chan<- string, query <-chan chan int) {
buffer := []string{}
var s string
var reply chan int
for {
// Go的选择语句不支持布尔条件,所以我们需要在选择语句外使用“if”语句
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)
}
}
}
}
英文:
There is an alternative solution to this using a "queue" process that handles the queueing of messages and also is able to report on its size. For this you will need an input channel and an output channel, plus a query channel through which the size is obtained. Because there will be two input channels, you will need a select (a CSP 'choice') between them.
Here's a little demo of this in operation. The queue consists of a slice as a buffer and an input channel.
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)
}
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论