A channel carries typed values between goroutines. It is useful for coordinating work, but using a channel does not automatically make shared data safe. When parallel goroutines need to protect access to a shared resource, a mutex is generally the better fit. section 8.3
Choose the channel’s capacity for the behavior you need:
- Unbuffered: make(chan int) has no capacity. A send blocks until a receiver receives the value, providing a synchronization point. section 9.7
- Buffered: make(chan int, 1) lets a send proceed while space remains. A send blocks when the buffer is full; an available slot is not a rendezvous with a receiver. section 9.7
A buffered send is not an acknowledgment
Suppose one goroutine assigns i = 1 and then receives from ch, while another sends to ch and prints i. With make(chan struct{}, 1), the send can finish before the assignment: the print races with the write. Changing ch to make(chan struct{}) makes the send wait for the receive. The assignment then happens before the print. A send also happens before its corresponding receive completes, so channel operations can establish ordering—but the direction and buffering matter. section 8.4.2
i := 0
ch := make(chan struct{}, 1)
go func() {
i = 1
<-ch
}()
ch <- struct{}{}
fmt.Println(i)
Inspect the buffered version: the send need not wait for the goroutine that writes i. section 8.4.2
i := 0
ch := make(chan struct{}) #1
go func() {
i = 1
<-ch
}()
ch <- struct{}{}
fmt.Println(i)
Compare the unbuffered version: the send waits for the receive after the write. section 8.4.2
Case order does not prioritize a channel
A loop receiving messages and a disconnection notification might put the message case first in select, expecting to process every queued message before returning. If both receives can proceed, select chooses one pseudo-randomly; the disconnect case can win while messages remain. If queued messages must be handled before exit, receive the disconnect notification and then use a second select loop to drain available messages, returning when its default case runs. section 9.4
Use channels to communicate results or notifications between goroutines. Use an unbuffered channel when the send–receive meeting is required for synchronization; choose buffering when senders should be able to proceed without an immediate receiver. Specify buffer capacity deliberately rather than treating a larger buffer as a synchronization fix. section 8.3 section 9.7









