Help us understand the problem. What is going on with this article?

Go言語でチャネルとselect

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

najeira
Software developer。Google Cloud(特にApp Engine)とFlutterのGoogle Developers Expert。好きな言語はGo。他Flutter/Dart, Android, iOS, Python。
michael-inc
マイケルはコミュニティサービスをつくる会社、「Community Builder」です。インターネットを通して人生がより豊かになるよう、人がつながる場所をつくりつづけます。
https://michael-inc.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away