By Dinesh Panchananam


2015-03-10 07:28:47 8 Comments

While SayHello() executes as expected, the goroutine prints nothing.

package main

import "fmt"

func SayHello() {
    for i := 0; i < 10 ; i++ {
        fmt.Print(i, " ")
    }
}

func main() {
    SayHello()
    go SayHello()
}

2 comments

@icza 2015-03-10 07:32:45

When your main() function ends, your program ends as well. It does not wait for other goroutines to finish.

Quoting from the Go Language Specification: Program Execution:

Program execution begins by initializing the main package and then invoking the function main. When that function invocation returns, the program exits. It does not wait for other (non-main) goroutines to complete.

See this answer for more details.

You have to tell your main() function to wait for the SayHello() function started as a goroutine to complete. You can synchronize them with channels for example:

func SayHello(done chan int) {
    for i := 0; i < 10; i++ {
        fmt.Print(i, " ")
    }
    if done != nil {
        done <- 0 // Signal that we're done
    }
}

func main() {
    SayHello(nil) // Passing nil: we don't want notification here
    done := make(chan int)
    go SayHello(done)
    <-done // Wait until done signal arrives
}

Another alternative is to signal the completion by closing the channel:

func SayHello(done chan struct{}) {
    for i := 0; i < 10; i++ {
        fmt.Print(i, " ")
    }
    if done != nil {
        close(done) // Signal that we're done
    }
}

func main() {
    SayHello(nil) // Passing nil: we don't want notification here
    done := make(chan struct{})
    go SayHello(done)
    <-done // A receive from a closed channel returns the zero value immediately
}

Notes:

According to your edits/comments: if you want the 2 running SayHello() functions to print "mixed" numbers randomly: you have no guarantee to observe such behaviour. Again, see the aforementioned answer for more details. The Go Memory Model only guarantees that certain events happen before other events, you have no guarantee how 2 concurrent goroutines are executed.

You might experiment with it, but know that the result will not be deterministic. First you have to enable multiple active goroutines to be executed with:

runtime.GOMAXPROCS(2)

And second you have to first start SayHello() as a goroutine because your current code first executes SayHello() in the main goroutine and only once it finished starts the other one:

runtime.GOMAXPROCS(2)
done := make(chan struct{})
go SayHello(done) // FIRST START goroutine
SayHello(nil) // And then call SayHello() in the main goroutine
<-done // Wait for completion

@VonC 2015-03-10 07:40:03

Right, I just understood your edit after reading dave.cheney.net/2014/03/19/channel-axioms: A send to a nil channel blocks forever, A receive from a nil channel blocks forever.

@Dinesh Panchananam 2015-03-10 08:00:49

@icza please check edits.

@icza 2015-03-10 08:03:21

@DineshPanchananam What do you mean by "unorderly" fashion? You expect to see mixed numbers randomly from the 2 running SayHello() functions?

@Dinesh Panchananam 2015-03-10 08:11:50

@icza i guess that was a dumb edit.

@icza 2015-03-10 08:28:59

@DineshPanchananam I edited my answer to address this case. But in short, you have no guarantee to observe such behavior (and even if you do, it will not be deterministic).

@Sundrique 2015-03-10 07:52:39

Alternatively (to icza's answer) you can use WaitGroup from sync package and anonymous function to avoid altering original SayHello.

package main

import (
    "fmt"
    "sync"
)

func SayHello() {
    for i := 0; i < 10; i++ {
        fmt.Print(i, " ")
    }
}

func main() {
    SayHello()

    var wg sync.WaitGroup
    wg.Add(1)

    go func() {
        defer wg.Done()
        SayHello()
    }()

    wg.Wait()
}

In order to print numbers simultaneously run each print statement in separate routine like the following

package main

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(fnScopeI int) {
            defer wg.Done()

            // next two strings are here just to show routines work simultaneously
            amt := time.Duration(rand.Intn(250))
            time.Sleep(time.Millisecond * amt)

            fmt.Print(fnScopeI, " ")
        }(i)
    }

    wg.Wait()
}

@Dinesh Panchananam 2015-03-10 08:01:32

please check edits

@Sundrique 2015-03-10 08:05:24

@DineshPanchananam do you want to print each number in a separate routine?

@Dinesh Panchananam 2015-03-10 08:10:52

No. i expected something ""parallel""". but i think i'm wrong.

@Sundrique 2015-03-10 08:21:27

@DineshPanchananam check the second part of the answer

@user114241 2015-03-10 14:14:36

Also, please don't use a defer when there's only one function call (the first code example) - just move wg.Done() to after the function call. There's not need to use a defer in that situation.

Related Questions

Sponsored Content

1 Answered Questions

[SOLVED] Signal goroutines to stop with channel close

  • 2018-11-12 21:43:50
  • Chen A.
  • 339 View
  • 1 Score
  • 1 Answer
  • Tags:   go channel

4 Answered Questions

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

  • 2013-04-26 04:39:57
  • Ryan Bigg
  • 17969 View
  • 60 Score
  • 4 Answer
  • Tags:   go

2 Answered Questions

change variable from goroutine

  • 2018-07-11 14:15:09
  • abonec
  • 235 View
  • -4 Score
  • 2 Answer
  • Tags:   go goroutine

3 Answered Questions

[SOLVED] Stop goroutine execution on timeout

  • 2018-05-28 17:14:36
  • Pandurang Waghulde
  • 1505 View
  • 0 Score
  • 3 Answer
  • Tags:   go goroutine go-iris

3 Answered Questions

[SOLVED] Why is time.sleep required to run certain goroutines?

  • 2013-04-02 18:11:14
  • Darrrrrren
  • 11093 View
  • 26 Score
  • 3 Answer
  • Tags:   go goroutine

1 Answered Questions

[SOLVED] Different behavior of updating global variable in goroutine

  • 2017-08-10 07:23:00
  • wyhao31
  • 1061 View
  • -1 Score
  • 1 Answer
  • Tags:   go goroutine

1 Answered Questions

[SOLVED] why main goroutine always be the second to be invoked

4 Answered Questions

4 Answered Questions

[SOLVED] How do goroutines work? (or: goroutines and OS threads relation)

3 Answered Questions

[SOLVED] First goroutine example, weird results

  • 2013-09-03 19:20:45
  • tarrsalah
  • 273 View
  • 3 Score
  • 3 Answer
  • Tags:   go goroutine

Sponsored Content