1

I am looking through Go Bootcamp and am reading the Go Concurrency chapter right now. I have never used concurrency before in programming and don't understand the output of this program:

package main

import (
    "fmt"
    "time"
)

func say(s string) {
    for i := 0; i < 2; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }
}

func main() {
    go say("world")
    say("hello")
}

Output:

hello
world
hello

Program exited.

Can someone explain why "world" is not printed twice like "hello"? And maybe elucidate the idea of using concurrency?

Note, Go Playground link here.

Peter Brennan
  • 1,366
  • 12
  • 28
nonamorando
  • 1,556
  • 2
  • 14
  • 33

1 Answers1

5

A Go program exits when main returns. In this case, your program is not waiting for the final "world" to be printed in another goroutine before exiting.

The following code (playground) will ensure main never exits allowing the other goroutine to finish.

package main

import (
    "fmt"
    "time"
)

func say(s string) {
    for i := 0; i < 2; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }
}

func main() {
    go say("world")
    say("hello")
    select{}
}

As you may have noticed, this results in a deadlock because the program has no way to go forward. You may wish to add a channel or a sync.Waitgroup to ensure the program exits cleanly immediately after the other goroutine completes.

For example (playground):

func say(s string, ch chan<- bool) {
    for i := 0; i < 2; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }

    if ch != nil {
        close(ch)
    }
}

func main() {
    ch := make(chan bool)
    go say("world", ch)
    say("hello", nil)
    // wait for a signal that the other goroutine is done
    <-ch
}
Stephen Weinberg
  • 51,320
  • 14
  • 134
  • 113