Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to understand goroutines

Tags:

go

goroutine

I've been playing around with the following code from A Tour of Go, but I don't understand what is going on when I apply some minor changes. The original code is this

package main

import (
    "fmt"
    "time"
)

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

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

and it produces this

world
hello
hello
world
world
hello
hello
world
world
hello

which is OK: five times hello, five times world. I starts to get strange when I call

say("world")
go say("hello")

Now the output is just

world
world
world
world
world

No hello whatsoever. It gets even weirder with two goroutines

go say("world")
go say("hello")

Now there is no output at all. When I change i < 5 to i < 2 and call

go say("world")
say("hello")

I get

world
hello
hello

What am I missing here?

like image 581
chessweb Avatar asked Feb 08 '26 03:02

chessweb


1 Answers

In the case of

 say("world")
 go say("hello")

The "world" call must complete before the "hello" goroutine is started. The "hello" goroutine does not run or complete because main returns.

For

go say("world")
go say("hello")

the goroutines do not run or complete because main returns.

Use sync.WaitGroup to prevent main from exiting before the goroutines complete:

func say(wg *sync.WaitGroup, s string) {
  defer wg.Done()
  for i := 0; i < 5; i++ {
    time.Sleep(100 * time.Millisecond)
    fmt.Println(s)
  }
}

func main() {
  var wg sync.WaitGroup
  wg.Add(2)
  go say(&wg, "world")
  go say(&wg, "hello")
  wg.Wait()
}

playground example


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!