go runtime_error ai_generated true

panic: runtime error: close of nil channel

ID: go/panic-runtime-error-close-of-nil-channel

Also available as: JSON · Markdown · 中文
95%Fix Rate
89%Confidence
1Evidence
2023-01-20First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
go1.20 active
go1.21 active
go1.22 active

Root Cause

Attempting to close a channel variable that has not been initialized (nil) using close(ch).

generic

中文

尝试使用 close(ch) 关闭一个尚未初始化(空值)的通道变量。

Official Documentation

https://go.dev/ref/spec#Close

Workarounds

  1. 95% success Initialize the channel with make() before using: ch := make(chan T); defer close(ch)
    Initialize the channel with make() before using: ch := make(chan T); defer close(ch)
  2. 93% success Guard close with a nil check: if ch != nil { close(ch) } else { /* handle nil case */ }
    Guard close with a nil check: if ch != nil { close(ch) } else { /* handle nil case */ }
  3. 90% success Use sync.Once to ensure close is called only once and after initialization: var closeOnce sync.Once; closeOnce.Do(func() { close(ch) })
    Use sync.Once to ensure close is called only once and after initialization: var closeOnce sync.Once; closeOnce.Do(func() { close(ch) })

中文步骤

  1. 使用 make() 初始化通道后再使用:ch := make(chan T); defer close(ch)
  2. 在 close 前进行空值检查:if ch != nil { close(ch) } else { /* 处理空值情况 */ }
  3. 使用 sync.Once 确保 close 只调用一次且在初始化之后:var closeOnce sync.Once; closeOnce.Do(func() { close(ch) })

Dead Ends

Common approaches that don't work:

  1. Wrap close(ch) in a recover() block to catch the panic 70% fail

    Recovering doesn't fix the root cause and may mask a logic error

  2. Use select with default to check if channel is nil before closing 80% fail

    select doesn't detect nil channels at compile time; it's a runtime check that still panics if nil

  3. Set ch = make(chan T) before every close call 60% fail

    Overwrites the existing channel and may cause goroutine leaks or lost messages