close of closed channel パニックの原因と直し方
一度closeしたチャネルをもう一度closeしようとすると、実行時にパニックが発生します。複数箇所からcloseを呼びうるコードでは、どこか1箇所だけが責任を持つ設計にする必要があります。
エラーメッセージの読み方
panic: close of closed channel
panic- パニック — 実行時に回復不能な状態になったことを示します。deferとrecoverで捕まえない限り、そのままプロセスが終了します
close of closed channel- 詳細メッセージ — どの値が問題だったか
このエラーが出る典型パターン
パターン1
1 package main 2 3 func main() { 4 ch := make(chan int) 5 close(ch) 6 close(ch) ^ 7 }
panic: close of closed channel
一度closeしたチャネルをもう一度closeすると、無視されずに実行時パニックになります。
直し方: close(ch) を _ = ch にします。
広告
広告スロット(未設定)
パターン2
1 package main 2 3 func main() { 4 ch := make(chan string) 5 close(ch) 6 close(ch) ^ 7 }
panic: close of closed channel
複数箇所からcloseを呼びうるコードでは、どこか1箇所だけが責任を持つように設計する必要があります。
直し方: close(ch) を _ = ch にします。
パターン3
1 package main 2 3 func main() { 4 ch := make(chan bool) 5 close(ch) 6 close(ch) ^ 7 }
panic: close of closed channel
送信側と受信側の両方がcloseを呼ぶような設計は、2回目のcloseでパニックする典型的な原因です。
直し方: close(ch) を _ = ch にします。
パターン4
1 package main 2 3 func main() { 4 ch := make(chan int, 2) 5 close(ch) 6 close(ch) ^ 7 }
panic: close of closed channel
バッファ付きチャネルでも、closeの二重呼び出しに対する挙動は変わりません。
直し方: close(ch) を _ = ch にします。
パターン5
1 package main 2 3 func main() { 4 ch := make(chan float64) 5 close(ch) 6 close(ch) ^ 7 }
panic: close of closed channel
closeされているかどうかは呼び出し側からは分からないため、二重closeを防ぐ設計上の工夫が必要です。
直し方: close(ch) を _ = ch にします。
よくある誤解
「closeを複数回呼んでも、2回目以降は何もしない安全な操作のはず」という思い込みは誤りです。2回目のcloseは黙って無視されず、その場でパニックします。
まとめ
close of closed channel パニックの原因と直し方は中級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。