16.5 ゴルーチン間のイベント伝達
チャネルはゴルーチンセーフなデータ構造で、送信元から受信先へ「データ」を伝達します。しかし、何かしらのデータではなく「何かが発生した」というイベントだけを通知したいことがあります。たとえばタスクが完了したという通知などです。Goのライブラリでは、サイズゼロの空の構造体を使ったチャネルがよく利用されています。
// ゼロバイトの構造体のチャネル
wait := make(chan struct{})
// 受信
<-wait
このチャネルを使って通知する場合には、空の構造体のインスタンスを送ります。
// 送信
wait <- struct{}{}
上記のようにイベントを送信すると、イベントを受信する複数のゴルーチンのうち、1つだけがイベントを受け取れます。複数のチャネルへイベントをブロードキャストしたい、かつそのイベントが1度だけ発生する場合には、チャネルをクローズする方法があります。
// 送信の代わりにクローズ
close(wait)
チャネルをクローズすると、同じチャネルを監視しているすべてのゴルーチンへ一斉に通知が行きます。これはイベントをブロードキャストしているのと同じ効果があります。一度クローズしたあと、そのチャネルへ再度読み込みに行こうとするとブロックせずにゼロ値が返ります。
チャネルの送信を用いて通知を行うと、1つの相手に1件のみ厳密に伝わります。相手が見えているのであればチャネルの送信でも良いですが、ささいなミスでブロッキングし続けることもあるため、クローズの方が安心です。
チャネルは誰も参照しなくなれば、クローズしなくてもガベージコレクタに回収されますが、たとえば、どこかのゴルーチンで読み込みを続けていると、それがブロックされ続けて、チャネルリークの原因となります。 ...
Get 実用 Go言語 ―システム開発の現場で知っておきたいアドバイス now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.