-1

In the below code:

package main

import (
    "context"
    "fmt"
    "time"
)

func cancellation() {
    duration := 150 * time.Millisecond
    ctx, cancel := context.WithTimeout(context.Background(), duration)
    defer cancel()

    ch := make(chan string)

    go func() {
        time.Sleep(time.Duration(500) * time.Millisecond)
        ch <- "paper"
    }()

    select {
    case d := <-ch:
        fmt.Println("work complete", d)
    case <-ctx.Done():
        fmt.Println("work cancelled")
    }

    time.Sleep(time.Second)
    fmt.Println("--------------------------------------")
}

func main() {
    cancellation()
}

Because of unbuffered channel(ch := make(chan string)), go-routine leaks due to block on send(ch <- "paper"), if main goroutine is not ready to receive.

Using buffered channel ch := make(chan string, 1) does not block send(ch <- "paper")

How to detect such go-routine leaks?

kostix
  • 51,517
  • 14
  • 93
  • 176
overexchange
  • 15,768
  • 30
  • 152
  • 347
  • Does this answer your question? [How to dump goroutine stacktraces?](https://stackoverflow.com/questions/19094099/how-to-dump-goroutine-stacktraces) –  Nov 08 '20 at 10:27

1 Answers1

1

There are some packages that let you do that. Two that I've used in the past:

Generally, they use functionality from the runtime package to examine the stack before and after your code runs and report suspected leaks. It's recommended to use them in tests. I found this works well in practice and used it in a couple of projects.

Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412
  • see also this comment, and all the post in general, https://stackoverflow.com/a/19145992/4466350 –  Nov 08 '20 at 10:28
  • @mh-cbon: I think this is reasonable as a separate question; making the connection between "how to I know if I have goroutine leaks" and "oh I need to look at the stack" is nontrivial. But YMMV. – Eli Bendersky Nov 08 '20 at 15:10