列出缓冲通道中的所有元素。

huangapple go评论68阅读模式
英文:

list all elements in a buffered channel

问题

有没有一种(非破坏性的)方法可以列出缓冲通道中的所有元素?

我唯一能想到的方法是循环遍历它们,将它们重新插入到末尾。这似乎不是最聪明的方法。

Playground链接

c := make(chan int, 100)
c <- 111
c <- 222
for i:=0;i<2;i++ {
element := <- c
fmt.Println(element)
c <- element
}
fmt.Println(len(c))
英文:

Is there a (non destructive) way to list all the element in a buffered channel?

The only thing I can think about is to cycle all of them, reinserting them at the end. This doesn't seem the smartest approach.

Link to playground

c := make(chan int, 100)
c &lt;- 111
c &lt;- 222
for i:=0;i&lt;2;i++ {
element := &lt;- c
fmt.Println(element)
c &lt;- element
}
fmt.Println(len(c))

答案1

得分: 5

不,你不能这样做,如果你想要的话,你可以基于列表编写自己的阻塞队列。

英文:

No you can't, you can write your own blocking queue based on a list if you want to do that.

答案2

得分: 4

这个2011年的帖子提供了一些关于通道的封装,以实现Peek()函数,但那更像是一种变通方法。

type PeekChanInt struct {
        in <-chan int
        out chan int
}

总的结论是:

> 同步通道没有头部(就像一个长度为零的切片)

> 你不能这样做,因为

> - a) 它会被放回队列的尾部而不是末尾,以及

  • b) 一个写入者可能已经到达那里,所以写入可能会被阻塞。

> 我过去曾经想要这样的功能。当通道只有一个消费者时,这是有意义的(我想要它来查看第一个鼠标事件,以便在决定是否消费它之前进行命中测试)

> 你可以用一个充当中间人的进程来模拟它,但你必须为每种通道类型都这样做,否则就会失去类型安全性。

> 记住,没有缓冲区,所以如果你查看一个值,你必须从另一边获取该值,这相当于读取它 - 但这是错误的,因为查看不应该有副作用

英文:

This thread from 2011 offered some wrapper around a channel in order to enable a Peek() function, but that was more a workaround than anything else.

type PeekChanInt struct {
        in &lt;-chan int
        out chan int
}

The general conclusion was:

> A synchronous channel has no head (it's like a zero-length slice)

> You can't do that because

> - a) it gets put back at the tail of the queue rather than the end and

  • b) a writer may have got there first, so the put may block.

> I have wanted a feature like this in the past. It can make sense when there is only one consumer of the channel (I wanted it to peek at the first mouse event to do hit testing before deciding whether to consume it)

> You can simulate it with a process acting as intermediary, but you'd have to do it for each channel type or lose type safety.

> Remember there is no buffering, so if you peek at a value, you'd have to get the value from the other side, which would be equivalent to reading it - but that's wrong because peeking should have no side effects.

答案3

得分: 1

你不能真正做到。你所拥有的是唯一的方法,但如果chan存在任何并发访问(那么你为什么要使用chan?),就不要这样做。

在你检查len之后,项目可能会被插入或移除,在你的for循环期间也可能发生这种情况。

英文:

You can't really. What you have is the only way, but don't do that if there's any concurrent access to the chan (and then why are you using a chan?).

Items could be inserted or removed after you check len, and during your for loop.

huangapple
  • 本文由 发表于 2014年9月26日 02:40:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/26045787.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定