channelpolicy
Checks channel capacity and closing ownership.
What it detects
Reports channels with large constant capacities that have no nearby rationale, code that closes a channel received from its caller, and sends that can happen after the channel has been closed.
Checks
| Check | What it detects |
|---|---|
capacity-rationale* |
Reports large constant channel capacities without a nearby bounded rationale. |
caller-close |
Reports functions that close channels received from their callers. |
send-after-close |
Reports sends reachable after a channel has been closed. |
* Opt-in; requires explicit selection.
Why this is flagged
Closing a channel from the wrong place can race with a sender and panic. Giving one owner responsibility for closing makes the channel’s lifetime predictable; avoiding unexplained large buffers also keeps backpressure problems visible.
Further reading: Go concurrency patterns: Pipelines and cancellation.
How to fix it
Let the code that creates and sends on the channel close it after the last send. Prefer an unbuffered or small channel unless the larger capacity has a clear, documented reason.
Examples
Flagged code
func consume(events chan Event) { // gohawk: do not close a channel received from caller defer close(events) for event := range events { handle(event) }}Accepted code
func consumeSafely(events <-chan Event) { for event := range events { handle(event) }}Options
| Knob | Default | Effect |
|---|---|---|
max-unexplained-capacity |
1 |
Largest channel capacity allowed without a rationale; negative disables the check. |