web-dev-qa-db-ja.com

Golang-バッファリングされたチャンネルが一杯であることを知る方法

バッファリングされたチャネルがいっぱいであることを知る方法は?バッファリングされたチャネルが一杯になったときにブロックされるかどうかはわかりませんが、代わりに、バッファリングされたチャネルに送信されたアイテムをドロップすることを選択します。

34
GarudaReiga

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

送信せずに確認する

Go仕様 で説明されているように、len(ch)を使用して、チャネルでキューに入れられている要素の数を確認することもできます。これと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ブロックを入力するまでに、比較の結果が無効になる可能性があることに注意してください。

86
ANisus

代わりに、バッファされたチャネルに送信されたアイテムをドロップすることを選択します。

それは「オーバーフローチャネル」と呼ばれ、 eapache/channels/overflowing_channel.go

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を参照してください。

11
VonC

私が偶然見つけた別の有用な例は、 この気の利いた実装リングバッファー でした。

ソースからの引用:

アイデアは簡単です。着信チャンネルから発信チャンネルにメッセージを転送する1つのGoroutineを介して2つのバッファー付きチャンネルを接続します。新しいメッセージを発信チャネルに配置できない場合は常に、発信チャネルから1つのメッセージ(つまり、バッファ内の最も古いメッセージ)を取り出してドロップし、新しく解放された発信チャネルに新しいメッセージを配置します。

このCバージョン もチェックしてください...

1
Ostati