-2

I am new to Go language programming and learning it step by step.
While practicing it, I found random behavior of goroutines.
If I call goroutine (function having sleep of 1 second), some times it completed successfully and some times it doesn't:

package main

import (
    "fmt"
    "time"
)

func t(i int) {
    fmt.Println("In func t")
    time.Sleep(1)
}

func t1(i int) {
    fmt.Println("In func t1")
    time.Sleep(1)
}

func main() {
    fmt.Println("Hello Good Morning")
    go t(1)
    t1(2)
    time.Sleep(5)
    fmt.Println("End of func main")
}

O/p 1 :

  Hello Good Morning
  In func t1
  In func t
  End of func main

O/p 2 :

  Hello Good Morning
  In func t1
  End of func main

Could someone explain why goroutine is not guaranteeing the execution of that goroutine function call.

Prakash Kumar
  • 79
  • 1
  • 11

2 Answers2

1

Program execution:

When the function main returns, the program exits. It does not wait for other (non-main) goroutines to complete.

1- main is goroutine too, you need to wait for other goroutines to finish, and you may use

time.Sleep(5 * time.Second)

for 5 Seconds wait, try it on The Go Playground:

package main

import (
    "fmt"
    "time"
)

func t(i int) {
    fmt.Println("In func t")
    time.Sleep(1 * time.Second)
}

func t1(i int) {
    fmt.Println("In func t1")
    time.Sleep(1 * time.Second)
}

func main() {
    fmt.Println("Hello Good Morning")
    go t(1)
    t1(2)
    time.Sleep(5 * time.Second)
    fmt.Println("End of func main")
}

output:

Hello Good Morning
In func t1
In func t
End of func main

And see Docs:

// Sleep pauses the current goroutine for at least the duration d.
// A negative or zero duration causes Sleep to return immediately.
func Sleep(d Duration)

2- You may use sync.WaitGroup to wait for other goroutines, try it on The Go Playground:

package main

import (
    "fmt"
    "sync"
    "time"
)

var w sync.WaitGroup

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

func main() {
    w.Add(1)
    go say("A")

    w.Add(1)
    say("B")

    w.Wait()
}

output:

B
A
A
B
0

Two things:

  1. If you return from main without having explicitly waited for your goroutine to finish, there's no guarantee that it will finish before the program exits.
  2. The argument type of time.Sleep() is time.Duration, the units of which are nanoseconds. Since you're barely delaying at all, it's not surprising that your results were random. If you sleep for a more substantial amount of time in main, you should see both lines printed (although it isn't guaranteed).

If you need to wait for a goroutine to finish, there are various ways to do that (e.g, channels and sync.WaitGroup).

You may want to go through A Tour of Go and/or take a look at Effective Go.

Andy Schweig
  • 6,597
  • 2
  • 16
  • 22