Skip to content

Instantly share code, notes, and snippets.

@thenewvu
Created November 11, 2017 07:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thenewvu/a155013918d9b708a77db5bf29b5e359 to your computer and use it in GitHub Desktop.
Save thenewvu/a155013918d9b708a77db5bf29b5e359 to your computer and use it in GitHub Desktop.
20171111.log.md

Learn Golang: fmt.Println doesn't print anything in goroutines

Run the below example, you will see there was nothing printed from fmt.Println in exec(), why?

func longexec (name) {
  // simulate long execution
  for p := 0; p < 10 ; p++ {
    filled := strings.Repeat("=", p+1)
    empty := strings.Repeat(" ", finish-p-1)
    fmt.Printf("%s [%s%s]\n", name, filled, empty)
    dur := time.Duration(rand.Intn(100))
    time.Sleep(dur * time.Millisecond)
  }
}

func main () {
  go longexec("Thread 1")
  go longexec("Thread 2")
}

The reason is, those 2 goroutines Thread 1 and Thread 2 didn't have enough time to be executed because main() was finished immediately after creating them.

To give them time to execute, there're many ways, a common way is using channels. Receiving data from channels will be blocked until the sender side sends some data.

func exec (name, ch chan string) {
  // simulate long execution
  for p := 0; p < 10 ; p++ {
    filled := strings.Repeat("=", p+1)
    empty := strings.Repeat(" ", finish-p-1)
    fmt.Printf("%s [%s%s]\n", name, filled, empty)
    dur := time.Duration(rand.Intn(100))
    time.Sleep(dur * time.Millisecond)
  }
  // notify this thread has finished
  ch <- name
}

func main () {
  ch := make(chan string)
  go exec("Thread 1", ch)
  go exec("Thread 2", ch)
  fmt.Println('Finished', <- ch) // wait for the first finished thread
  fmt.Println('Finished', <- ch) // wait for the second finished thread
}

Why does fmt.Println inside a goroutine not print a line?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment