The close function marks a channel unable to accept further sends and lets receivers detect completion. An attempted send after closing panics, so a sender should normally close the channel with protective coordination. section 5.3.2
Use these behaviors when designing channel shutdown:
- Close from the sender after sending is finished; closing from a receiver while another goroutine sends can panic. section 5.3.2
- Receive with m, ok := <-ch; ok becomes false after closure, while further receives produce the channel’s zero value. section 5.3.2
- Coordinate shutdown with a separate done channel, allowing the receiver to signal completion before the sender closes the message channel. section 5.3.2
Listing 5.8 Improper channel close
package main
import (
"fmt"
"time"
)
func main() {
msg := make(chan string)
until := time.After(5 * time.Second)
go send(msg) #1
for { #2
select {
case m := <-msg: #3
fmt.Println(m)
case <-until: #4
close(msg) #4
time.Sleep(500 * time.Millisecond) #4
return #4
} #4
}
}
func send(ch chan string) { #5
for {
ch <- "hello"
time.Sleep(500 * time.Millisecond)
}
}
See the runnable failure case where a timeout closes msg while send is still transmitting, producing a send-on-closed-channel panic. section 5.3.2
Coordinated channel closure
A sender can select on done, close the outbound channel when shutdown is signaled, and return. This separates completion signaling from the data channel. section 5.3.2


