Chapter 13 - Goroutines and Channels

Exercise 1: Goroutines and Channels

Here’s our program that runs the a and b functions in goroutines again. Previously, we used time.Sleep(time.Second) to keep the main goroutine from exiting until the other goroutines finished. But these functions don’t take anywhere near a second to finish, meaning it takes longer than necessary for the program to complete.

Revise the a and b functions to accept a channel as a parameter. Each function should send a value to the channel when its work is complete. We just want to use the channel for synchronization, so the values sent don’t really matter; we suggest bool values.

In main, you’ll need to create the channel you’re going to use. Call a in a new goroutine, passing the channel as an argument. Do the same for b. (You can pass a single channel to both functions.) Finally, read from the channel twice. Each read will cause the main goroutine to block, allowing the other two goroutines to complete before the program exits.

package main

import (
	"fmt"
	"time"
)

func a() {
	for i := 0; i < 50; i++ {
		fmt.Print("a")
	}
}

func b() {
	for i := 0; i < 50; i++ {
		fmt.Print("b")
	}
}

func main() {
	go a()
	go b()
	time.Sleep(time.Second)
	fmt.Println("end main()")
}

Example Output:

bbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaend main()

Note: The Go Playground can’t run the goroutines in parallel, meaning that one goroutine will always complete before the other starts. You won’t be able to see the program switch back and forth between the goroutines unless you run it on a computer with a multi-core processor.

When you’re ready, have a look at our solution.