Channel synchronization helps different parts of a Go program talk to each other safely and wait for each other when needed.
Channel synchronization in Go
ch := make(chan Type) // Send value to channel ch <- value // Receive value from channel value := <-ch
Channels are typed, so you must specify the type of data they carry.
Sending and receiving on channels can block (wait) until the other side is ready, which helps with synchronization.
ch := make(chan int) // Sending ch <- 5 // Receiving num := <-ch
done := make(chan bool)
go func() {
// Do some work
done <- true // Signal completion
}()
<-done // Wait for signalThis program starts a worker goroutine that prints a message and then signals completion through a channel. The main function waits for this signal before printing its final message.
package main import ( "fmt" ) func worker(done chan bool) { fmt.Println("Working...") done <- true // Signal that work is done } func main() { done := make(chan bool) go worker(done) <-done // Wait for worker to finish fmt.Println("Worker finished") }
Channels block the sender until the receiver is ready, and vice versa, which helps coordinate tasks.
Buffered channels can hold some values without blocking, but unbuffered channels always synchronize sender and receiver.
Always close channels only when you want to signal no more values will be sent; closing a channel is not needed for synchronization.
Channels let goroutines communicate and wait for each other safely.
Sending and receiving on channels can pause execution until the other side is ready, which helps with synchronization.
Use channels to coordinate tasks and share data between goroutines without conflicts.
Practice
Solution
Step 1: Understand unbuffered channel behavior
Unbuffered channels require both sender and receiver to be ready at the same time for communication.Step 2: Analyze sending on unbuffered channel
If no goroutine is ready to receive, the sending goroutine blocks and waits until a receiver is ready.Final Answer:
The sending goroutine waits until another goroutine receives the data. -> Option AQuick Check:
Unbuffered channel send blocks until receive [OK]
- Thinking data is buffered automatically
- Assuming send never blocks
- Believing program crashes on send
Solution
Step 1: Recall channel creation syntax
Channels are created using make with type and optional buffer size: make(chan Type, capacity).Step 2: Identify correct buffered channel syntax
To create a buffered channel of int with capacity 3, use make(chan int, 3).Final Answer:
ch := make(chan int, 3) -> Option CQuick Check:
Buffered channel syntax = make(chan Type, capacity) [OK]
- Omitting buffer size for buffered channel
- Using new() instead of make()
- Incorrect channel literal syntax
package main
import "fmt"
func main() {
ch := make(chan string)
go func() {
ch <- "hello"
}()
msg := <-ch
fmt.Println(msg)
}Solution
Step 1: Analyze channel and goroutine
A goroutine sends "hello" on an unbuffered channel ch, while main receives from ch.Step 2: Understand synchronization
The send and receive synchronize, so main receives "hello" and prints it.Final Answer:
hello -> Option DQuick Check:
Send and receive synchronize, printing message [OK]
- Expecting deadlock because of goroutine
- Thinking channel is buffered by default
- Assuming no output due to concurrency
package main
func main() {
ch := make(chan int)
ch <- 5
val := <-ch
println(val)
}Solution
Step 1: Check channel creation and usage
Channel ch is unbuffered and created correctly with make(chan int).Step 2: Analyze send operation
Sending on unbuffered channel blocks until another goroutine receives. Here, send happens before receive, no other goroutine receives, so it blocks forever.Final Answer:
Sending on channel blocks forever causing deadlock. -> Option BQuick Check:
Send blocks without concurrent receiver [OK]
- Thinking receive blocks first
- Assuming channel is nil
- Believing code runs without deadlock
Solution
Step 1: Understand synchronization goal
Main must wait for all 3 goroutines to finish before exiting.Step 2: Analyze channel usage options
Buffered channel with capacity 3 allows all goroutines to send done signals without blocking; main receives 3 signals to know all finished.Final Answer:
Use a buffered channel with capacity 3; each goroutine sends a signal when done; main receives 3 signals. -> Option AQuick Check:
Buffered channel capacity = number of goroutines to sync [OK]
- Using unbuffered channel causing deadlock
- Receiving fewer signals than goroutines
- Not waiting for goroutines at all
Ready to prove it?
Pass the test and this pattern moves unknown
