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
となる。