-1

I have this code:

func sleep(d time.Duration, ch chan<- int) {
    fmt.Println("Sleeping...")
    time.Sleep(d)
    fmt.Println("Awake...")
    ch <- 0
}

func parent(ctx context.Context) int {
    ch := make(chan int, 1)

    go sleep(3*time.Second, ch)

    select {
    case <-ctx.Done():
        return 1
    case <-ch:
        return 0
    }
}

func app(wg *sync.WaitGroup) {
    defer wg.Done()

    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()

    res := parent(ctx)

    fmt.Println(res)
}

func main() {

    var wg sync.WaitGroup
    wg.Add(1)

    go app(&wg)

    wg.Wait()

    time.Sleep(2 * time.Second)
}

In this example, I have a ctx with 2 seconds timeout.
It takes 3 seconds for childFunc to end its process.
After 2 seconds the parent func returns 1 because of case <-ctx.Done().
But in the main thread I sleep for 2 more seconds and I see the childFund hasn't exited and is continuing its process and the Awake... will be printed.
Why childFunc doesn't exit when its parent goroutine finishes?

Here is the output:

Sleeping...
1
Awake...
Mojtaba Arezoomand
  • 2,140
  • 8
  • 23

1 Answers1

2

I think you're asking why a goroutine doesn't exit when the goroutine that created it exits. Except for the main goroutine (which when it exits, the whole program including all goroutines exit), goroutines are independent when they launch -- they don't have a "parent" and there's no way to stop them from outside, including termination of the goroutine that launched them. If you want a goroutine to be killable then you have to code it yourself, for example by returning from the goroutine when the passed-in context is cancelled.

Paul Hankin
  • 54,811
  • 11
  • 92
  • 118