Search code examples
gomemory-leakstimeout

timeout on function and goroutine leak


I wish to put a timeout on a function called foo. Consider the following

func fooWithTimeout(d time.Duration) error {
    ch := make(chan error, 1)
    go func() {
        ch <- foo()
    }()

    select {
    case err := <-ch:
        return err
    case <-time.After(d):
        return errors.New("foo has timed out")
    }
}
  • If foo has timed out, then will foo ever be able to write to channel ch or is there a risk the goroutine blocks or panics?
  • What happens to channel ch once fooWithTimeout has exited?
  • Is this code potentially problematic?
  • Should I add defer close(ch) within go func(){...}() just before calling foo?
  • Does it matter that I use a buffered (with size 1) or an unbuffered channel in this example?

Solution

  • After the timer tick, fooWithTimeout will return. The goroutine will continue running until foo returns.

    If foo times out, it will write to channel ch because it is buffered.

    The channel ch will be garbage collected eventually if foo returns.

    You don't need to close the channel. Once it is out of scope, it will be garbage collected.

    A large burst of calls fooWithTimeout will create large amount of resources. Each call creates two goroutines. The proper way of timing this out is to change foo to use a context.