2 ms·
I'm not sold on Martin's proposal, however I recently spent some time getting clean cancellation into some code I was working on so I can sympathize with what h
by bmurphy1976 11y ago
I'm not sold on Martin's proposal, however I recently spent some time getting clean cancellation into some code I was working on so I can sympathize with what he is going through. Here are a few tips that will hopefully help others who face a similar situation:
1. The simplest way to cancel something is to have a "cancelled" channel and close it, don't send a cancel message! This is important because closing the channel acts as a broadcast. Multiple goroutines can listen for the same signal and you don't have to spend time managing who's sending what message to whom and when. Close the channel and everybody is immediately notified.
2. You can select on both send and receive. You should check if the cancelled channel has been closed on sends so that your goroutines don't block forever. It's incredibly difficult to guarantee that somebody will be listening on the channel to unblock your goroutine after cancellation happens, so you should check on send as well.
Example receive:
select {
case message := <-c:
// do something with message
case <-cancelled:
// cleanup and exit goroutine
}
Example send:
select {
case c <- message:
case <-cancelled:
// cleanup and exit goroutine
}
3. One commenter asked Martin why he doesn't use the standardized context package. Martin replied stating there is no way to distinguish between hard and soft cancels. While this is true, given a single context, there's nothing saying you can't use more than one context or cancellation channel. I'm not saying this is a particularly good idea, but these are not singletons and you can have as many as you need.
Doing cancellation cleanly is still a tough problem, but with some focus and especially #1 and #2 it's doable, but you have to roll up your sleeves and put some effort into it.
- rumcajz 11y agoThanks for making the above clear. I should probably have made that explicit in the article but I was so focused on hard cancellation that all I've said about soft cancellation was, basically, "do it by hand", without going into details. In fact, being able to share single channel between multiple goroutines and using "close" as a broadcast mechanism is one of the best -- if rarely mentioned -- ideas in Go.