-3

I'm recently looking into Golang by google and I met with the following problem. Then program doesn't print anything. But if I remove the "go" notations, it will print both "goroutine" and "going".

package main

import "fmt"

func f(msg string) {
    fmt.Println(msg)
    return
}

func main() {
    go f("goroutine")

    go func(msg string) {
        fmt.Println(msg)
        return
    }("going")

    return
}
Kavu
  • 7,886
  • 3
  • 34
  • 39
SaunTang
  • 1
  • 2
  • 2
    Because main exits before gorutines are run. Also this question is asked every other day – Arjan Feb 13 '14 at 17:30

2 Answers2

8

You program exits before the goroutines is executed. You could wait a little bit, for example by calling time.Sleep(2 * time.Second), but such behaviour is considered bad practice, since your program could run longer than 2 seconds and would then terminate nonetheless.

A better approach is to use sync.WaitGroup:

package main

import (
    "fmt"
    "sync"
)

func f(msg string, wg *sync.WaitGroup) {
    fmt.Println(msg)
    wg.Done()
}

func main() {
    var wg sync.WaitGroup

    wg.Add(1)
    go f("goroutine", &wg)

    wg.Add(1)
    go func(msg string) {
        fmt.Println(msg)
        wg.Done()
    }("going")

    wg.Wait()
}
fresskoma
  • 25,481
  • 10
  • 85
  • 128
Kavu
  • 7,886
  • 3
  • 34
  • 39
  • 2
    Uargh. That's the worst advice. Use channels or `sync.WaitGroup`. – nemo Feb 13 '14 at 17:32
  • 1
    And wrong in case the goroutine takes longer than 2 seconds. Your answer should be a valid example, a guideline for good code. Yours is neither of both in this state. – nemo Feb 13 '14 at 17:34
  • 2
    Thanks for adding the WaitGroup example. I've removed the sleep example for better legibility, I hope you don't mind :) – fresskoma Feb 13 '14 at 17:41
5

Your code needs to wait for the routines to finish before exiting. A good way to do this is to pass in a channel which is used by the routine to signal when it's done and then wait in the main code. See below.

Another advantage of this approach is that it allows/encourages you to perform proper error handling based on the return value.

package main

import (
    "fmt"
)

func f(msg string, quit chan int) {
    fmt.Println(msg)
    quit <- 0
    return
}

func main() {

    ch1 := make(chan int)
    ch2 := make(chan int)

    go f("goroutine", ch1)

    go func(msg string, quit chan int) {
        fmt.Println(msg)
        quit <- 0
        return
    }("going", ch2)

    <-ch1
    <-ch2
    return
}
Usman Ismail
  • 17,999
  • 14
  • 83
  • 165