Before I talk about unbuffered channels, let me recap what channels are and how they help make concurrency easier in Go.
Channels synchronize go routines as they send and recieve resources they need between each other. When declaring channel we
use the make
keyword along with the type of data that we are going to share.
Unbuffered and Buffered channels behave differently and understanding both will help you decide which one is more suitable in a given scenario.
Unbuffered channel is channel with no capacity to hold any value before it's recieved.
unbuffered := make(chan int)
With unbuffered channels both go routines have to be ready at the same instant before the send or recieve operation is
complete. Synchronization
is inherent in the interaction between the send and the receive on the channel.
Once a go routine send data to an unbuffered channel it is locked till the recieving go routine recieves the data.
To understand this better, let's take a look at a program that simulates a relay race b/w 4 go routines
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
func main() {
// create an unbuffered channel
baton := make(chan int)
// add wait group for the last runner
wg.Add(1)
// launch first runner
go Runner(baton)
// start the race
baton <- 1
// wait for the race to finish
wg.Wait()
}
func Runner(baton chan int) {
var newRunner int
// wait to recieve baton
runner := <-baton
// start running
fmt.Printf("Runner %d running with baton\n", runner)
// new runner on the line
if runner != 4 {
newRunner = runner + 1
fmt.Printf("Runner %d to the line\n", newRunner)
go Runner(baton)
}
// run
time.Sleep(100 * time.Millisecond)
// is the race over?
if runner == 4 {
fmt.Printf("Runner %d finished. Race over.\n", runner)
wg.Done()
return
}
// exchange baton with the next runner
baton <- newRunner
}
// Runner 1 running with baton
// Runner 2 to the line
// Runner 2 running with baton
// Runner 3 to the line
// Runner 3 running with baton
// Runner 4 to the line
// Runner 4 running with baton
// Runner 4 finished. Race over.