LoginSignup
24
15

More than 5 years have passed since last update.

Go のバッファ付きチャネル close の挙動

Posted at

バッファ付きチャネルをcloseするとどうなるか

突然ですが、次のプログラムを動かした時の出力を答えてください。

package main

import "fmt"

func main() {
    // バッファ 2 のチャネル
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    close(ch)

    for n := range ch {
        fmt.Println(n)
    }
}

正解はこちら
https://play.golang.org/p/mDvIj--7zC

1
2

Program exited.

先にcloseされていますが、バッファに残っている値はすべてちゃんと読みだしてからcloseを判断しているようです。

チャネルの受信側には、すべての値が読み出されてから close 通知がくる

次のプログラムを動かして見ましょう

package main

import "fmt"

func main() {
    // バッファ 3 のチャネル
    ch := make(chan int, 3)
    ch <- 1
    ch <- 2
    close(ch)

    n1, ok1 := <- ch
    n2, ok2 := <- ch
    _, ok3 := <- ch

    fmt.Println(n1, ok1)
    fmt.Println(n2, ok2)    
    fmt.Println(ok3)
}

1 true
2 true
false

送信側からは、closeしたチャネルには値を送信できません

package main

func main() {
    // バッファ 3 のチャネル
    ch := make(chan int, 3)
    ch <- 1
    ch <- 2
    close(ch)

    ch <- 3
}

panic: send on closed channel

goroutine 1 [running]:
main.main()
    /tmp/sandbox997235944/main.go:10 +0x120

送信側は、チャネルがバッファ付きだろうがなかろうが、データを送りきってからcloseすれば良いわけです。
close するタイミングと、受信側でcloseされたと判断されるタイミングに時差があるので、結果的には直感的ですが、ちょっと戸惑う挙動かと思います。
あまり言及している記事がなかった記憶があるので、知っているとproducer-consumer パターンの実装の時に役立ちます。

24
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
15