如何知道缓冲频道已满?我不知道在缓冲频道已满时被阻止,而是我选择丢弃发送到缓冲频道的项目。
答案 0 :(得分:80)
您可以使用默认的select
statement。如果无法执行任何情况,例如发送到完整频道,则该语句将执行默认设置:
package main
import "fmt"
func main() {
ch := make(chan int, 1)
// Fill it up
ch <- 1
select {
case ch <- 2: // Put 2 in the channel unless it is full
default:
fmt.Println("Channel full. Discarding value")
}
}
<强>输出:强>
频道已满。丢弃价值
游乐场: http://play.golang.org/p/1QOLbj2Kz2
不发送检查
还可以使用len(ch)
检查频道中排队的元素数量,如Go specifications中所述。
结合cap
,我们可以检查频道是否已满而不发送任何数据。
if len(ch) == cap(ch) {
// Channel was full, but might not be by now
} else {
// Channel wasn't full, but might be by now
}
请注意,在您输入if
块
答案 1 :(得分:11)
相反,我选择删除发送到缓冲频道的项目。
这被称为“溢出频道”,您在eapache/channels/overflowing_channel.go
中找到了ANisus的答案:
for elem := range ch.input {
// if we can't write it immediately, drop it and move on
select {
case ch.output <- elem:
default:
}
}
close(ch.output)
但是该项目eapache/channels也实现了其他策略:
OverflowingChannel
以永不阻止作者的方式实现Channel
接口
具体来说,如果在缓冲区满时将值写入OverflowingChannel
(或者,在无缓冲的情况下,当收件人没有准备好时),那么该值就被丢弃了。对于相反的行为(丢弃最旧的元素,而不是最新的元素),请参阅
RingChannel
。
答案 2 :(得分:1)
我偶然发现的另一个有用的例子是this nifty implementation的Ring Buffer。
来自消息来源:
这个想法很简单:将两个缓冲通道连接到一个 Goroutine将来自传入频道的消息转发给 传出渠道。每当新消息无法放在上面时 传出通道,从传出通道中取出一条消息(即 是缓冲区中最旧的消息),删除它,并放置新的消息 新释放的传出频道中的消息。
同时查看this C version ...
答案 3 :(得分:0)
如果频道已满,我将使用此代码删除一项。对于只有一个发送go例程的频道,足以确保以后发送到ch
了。
// Remove one item from chan if full
if len(ch) == cap(ch) {
// Channel was full, but might not be by now
select {
case _ := <-ch:
// Discard one item
default:
// Maybe it was empty already
}
}
// Now we can send to channel