Exercises

Channels

  • Modify the program you created in exercise to usechannels, in other words, the function called in the body should now bea goroutine and communication should happen via channels. You should notworry yourself on how the goroutine terminates.

  • There are a few annoying issues left if you resolve question 1 above. One ofthe problems is that the goroutine isn’t neatly cleaned up when main.main()exits. And worse, due to a race condition between the exit of main.main()and main.shower() not all numbers are printed. It should print up until 9,but sometimes it prints only to 8. Adding a second quit-channel you canremedy both issues. Do this.

Answer

  • A possible program is:
  1. package main
  2. import "fmt"
  3. func main() {
  4. ch := make(chan int)
  5. go shower(ch)
  6. for i := 0; i < 10; i++ {
  7. ch <- i
  8. }
  9. }
  10. func shower(c chan int) {
  11. for {
  12. j := <-c
  13. fmt.Printf("%d\n", j)
  14. }
  15. }

We start in the usual way, then at line 6 we create a new channel of ints. In the next line we fire off the function shower with the ch variable as it argument, so that we may communicate with it. Next we start our for-loop (lines 8-10) and in the loop we send (with <-) our number to the function (now a goroutine) shower.

In the function shower we wait (as this blocks) until we receive a number (line 15). Any received number is printed (line 16) and then continue the endless loop started on line 14.

  • An answer is
  1. package main
  2. import "fmt"
  3. func main() {
  4. ch := make(chan int)
  5. quit := make(chan bool)
  6. go shower(ch, quit)
  7. for i := 0; i < 10; i++ {
  8. ch <- i
  9. }
  10. quit <- false // or true, does not matter
  11. }
  12. func shower(c chan int, quit chan bool) {
  13. for {
  14. select {
  15. case j := <-c:
  16. fmt.Printf("%d\n", j)
  17. case <-quit:
  18. break
  19. }
  20. }
  21. }

On line 20 we read from the quit channel and we discard the value we read. We could have used q := <-quit, but then we would have used the variable only once — which is illegal in Go. Another trick you might have pulled out of your hat may be: _ = <-quit. This is valid in Go, but idomatic Go is the one given on line 20.

Fibonacci II

This is the same exercise as an earlier one inexercise. For completeness the complete question:

The Fibonacci sequence starts as follows: (1, 1, 2, 3, 5, 8, 13, \ldots)Or in mathematical terms:(x1 = 1; x_2 = 1; x_n = x{n-1} + > x_{n-2}\quad\forall n > 2).

Write a function that takes an int value and givesthat many terms of the Fibonacci sequence.

But now the twist: You must use channels.

Answer

The following program calculates the Fibonacci numbers using channels.

  1. package main
  2. import "fmt"
  3. func dup3(in <-chan int) (<-chan int, <-chan int, <-chan int) {
  4. a, b, c := make(chan int, 2), make(chan int, 2), make(chan int, 2)
  5. go func() {
  6. for {
  7. x := <-in
  8. a <- x
  9. b <- x
  10. c <- x
  11. }
  12. }()
  13. return a, b, c
  14. }
  15. func fib() <-chan int {
  16. x := make(chan int, 2)
  17. a, b, out := dup3(x)
  18. go func() {
  19. x <- 0
  20. x <- 1
  21. <-a
  22. for {
  23. x <- <-a+<-b
  24. }
  25. }()
  26. return out
  27. }
  28. func main() {
  29. x := fib()
  30. for i := 0; i < 10; i++ {
  31. fmt.Println(<-x)
  32. }
  33. }
  34. // See sdh33b.blogspot.com/2009/12/fibonacci-in-go.html