In the code below, a client is putting a string on a service's input channel and listening for a reply on either an output or an error channel.
The context is set with a 5ms timeout.
func (s service) run() {
<-s.input
go func() {
select {
case <-s.ctx.Done():
s.errs <- errors.New("ctx done")
return
}
}()
time.Sleep(10 * time.Millisecond)
s.output <- 42
fmt.Println("run exit")
}
The code times out correctly (due to the 10ms sleep) and outputs
error: ctx done
However, the "run exit" is never printed.
Question: Is there a goroutine leak with processes stuck on
s.output <- 42
Go Playground example
Context has timeout of 5 milliseconds and you sleep for 10 millisecond before this line s.output <-42
is run. So the context is timeout first and error occurs, that correct, but take a look at main
function:
select {
case o := <-s.output:
fmt.Println("output: ", o)
case err := <-s.errs:
fmt.Println("error: ", err)
}
The select
statement has reached case err := <-s.errs
so it will break the select and go to the end of main
function => program exit Even if s.output <- 42
is call simultaneously with s.errs <- errors.New("ctx done")
only one case has reached in select
statement, if you need to reach second case, put a loop around select statement