Channels
A common challenge when using threads is to coordinate the communication between them. Go provides a mechanism to solve this problem: channels.
- goroutines can communicate with each other using channels, which is a special type of variable.
- A channel can contain a value of any kind.
- A goroutine can send a value to a channel and another goroutine can receive it.
- Channels can be buffered or unbuffered.
Using channels
Unbuffered
var ch chan string
ch := make(chan string)
ch <- "hello"
message := <-ch
Example
func main() {
ch := make(chan int)
go func() {
ch <- 42
}()
fmt.Println(<-ch)
}
The
func()
here is an example of an anonymous function, or a lambda.
Buffered
We can also have buffered channels.
In this case we specify the number of values that can be stored in the channel.
ch := make(chan string, 2)
ch <- "hello"
ch <- "world"
fmt.Println(<-ch)
fmt.Println(<-ch)
If you pull a message from the buffer, the thread will wait until a message is sent to the channel.
Things to be aware of
- Deadlocks can occur if a channel is not closed.
close(channel)
Good practice: Use the
defer
keyword to close the channel and to keep code in related blocks.
Waitgroups
A waitgroup is a way to wait for a collection of goroutines to finish.
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println("Hello")
}()
wg.Wait()