👻

Go言語でチャネルとselect

2020/10/01に公開

Go言語でチャネルとselectを使う場合の挙動についてのメモ

受信

単純に書くと以下のようになる。

// ch は chan
v := <- ch

ところが、チャネルが close されている場合はゼロ値が受信される。

値を受信したのか close によってゼロ値になったのかを区別するには左辺の2つめの変数でbool値を受け取る。

v, ok := <- ch
if ok {
	fmt.Println(v)
} else {
	fmt.Println("closed")
}

この ok はチャネルから受信した場合は true 、そうでない場合は false が入る。

select

チャネルに値が入っていない場合、受信はブロックする。ブロックせずに処理を行いたい場合は select を使う。

select {
case v := <- ch:
	fmt.Println(v)
default:
	fmt.Println("no value")
}

ch に値が入っている場合は case v := <- ch ケースが実行される。ch に値が入っていない場合は default ケースが実行される。default ケースが実行された場合はチャネルからの値の受信は行われない。

この時もチャネルが close されているとブロックせず case v := <- ch が実行される。受信か close か区別したい場合は以下のようにする。

select {
case v, ok := <- ch:
	if ok {
		fmt.Println(v)
	} else {
		fmt.Println("closed")
	}
default:
	fmt.Println("no value")
}

送信

単純に書くと以下のようになる。

// ch は chan
ch <- v

select

チャネルに空きがない場合、送信はブロックする。ブロックせずに処理を行いたい場合は select を使う。

select {
case ch <- v:
	fmt.Println("sent")
default:
	fmt.Println("no capacity")
}

ch に空きがある場合は case ch <- v ケースが実行され "sent" 表示、空きがない場合は default ケースが実行され "no capacity" 表示となる。default ケースが実行された場合はチャネルへの値の送信は行われない。

なお close したチャネルに送信しようとすると panic: send on closed channel となる。

この記事はQiitaの記事をエクスポートしたものです

Discussion