Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No output from goroutine

Tags:

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() } 
like image 530
Dinesh Panchananam Avatar asked Mar 10 '15 07:03

Dinesh Panchananam


People also ask

How can I get my Goroutine results?

You can send the return value in a channel in the goroutine and then collect that value in the main function. This line will wait until a value is pushed to the result channel. As seen above the sumValue will be pushed to result channel by the function sum.

Is Goroutine blocked?

When we send data into the channel using a GoRoutine, it will be blocked until the data is consumed by another GoRoutine. When we receive data from channel using a GoRoutine, it will be blocked until the data is available in the channel.

Can you print Goroutine?

In this case, the main GoRoutine will not wait for another GoRoutine to complete and it will execute the line fmt. Println("hello from main") immediately and exit before the print() function can print its message.


1 Answers

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 
like image 103
icza Avatar answered Oct 04 '22 15:10

icza