Golang - 如何知道缓冲通道已满

时间:2014-09-04 04:16:24

标签: go channel

如何知道缓冲频道已满?我不知道在缓冲频道已满时被阻止,而是我选择丢弃发送到缓冲频道的项目。

4 个答案:

答案 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 implementationRing 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