A lot of people will do things like:
func (s *Server) HandleFoo(ctx context.Context, in *input) status {
ch <- workFor(in)
return status.Accepted
}
This will block on the channel write even if the context becomes cancelled. Instead, you really need to be explicit about what you want to block: func (s *Server) HandleFoo(ctx context.Context, in *input) status {
select {
case ch <- workFor(in):
return status.Accepted
case <- ctx.Done():
return status.Error("handle foo: wait for work to be accepted: %w", ctx.Err())
}
}
Now we don't wait for the work to be accepted if the caller decides it doesn't care about the job anymore.My impression from digging around the open source world is that nobody except me cares about this. So maybe I'm just crazy. But I really like not leaking goroutines on long-running programs, making Control-C behave gracefully, etc.