4 ms·
Why do you encourage avoiding it? Afaik it's the only way to early-abort an operation since Goroutines operate in a cooperative, not preemptive, paradigm. To be
by schrodinger 1y ago
Why do you encourage avoiding it? Afaik it's the only way to early-abort an operation since Goroutines operate in a cooperative, not preemptive, paradigm. To be very clear, I'm asking this completely in good faith looking to learn something new!
- pjmlp 1y agoYou are expecting them to actually check the value, there is nothing preemptive. Another approach is special messages over a side channel.
- deepsun 1y agoSo instead of a context you need to pass a a channel. Same problem.
- pjmlp 1y agoNot necessarily, that is one of the reasons OOP exists. Have a struct representing the set of associated activities, owning the channel.
- ozgrakkurt 1y agosoo, a context?
- ncruces 1y agoYou can take that view, yes. But if you store your context in a struct (which is not the recommend “best practice” – but which you can do) it's no longer a function coloring issue. I do that in on of my libraries and I feel that it's the right call (for that library).
- lenkite 1y agoIf the struct has a well-scoped and short-lived lifecycle, then it is actually better to put the context in the struct. Many Go libraries including the stdlib do this despite not being "best practice". An exception to the short-lived rule is to put context in your service struct and pass it as the base context when constructing the HTTP server, so that when you get a service shutdown signal, one can cancel requests gracefully.
- ncruces 1y agoIt's well scoped, but not short lived; it's an SQLite connection. But the API surface is huge, with 100s of methods on the connection and derived objects, with it being unclear which might block and be worthy of asynchronous cancellation. You never know when pulling an additional column if that one might be an overflow text/blob that does additional IO. The solution, while not amazing is a method that you use like this: old := conn.SetInterrupt(ctx) defer conn.SetInterrupt(old) This changes the “interrupt” context for the duration of your function scope, and covers all potentially blocking calls that you might make. Also, from the name, it's quite clear that this context is used only for interruption/cancellation (interrupt is the SQLite name for this, which I try to adhere to).
- pjmlp 1y agoNope, because I didn't mention it was to be passed around as a compulsory parameter, rather have your logic organised across structs with methods, hide most details behind interfaces.
- sapiogram 1y ago> Afaik it's the only way to early-abort an operation since Goroutines operate in a cooperative, not preemptive, paradigm. I'm not sure what you mean here. Preemptive/coorporative terminology refers to interrupting (not aborting) a CPU-bound task, in which case goroutines are fully preemptive on most platforms since Go 1.14, check the release notes for more info. However, this has nothing to do with context. If you're referring to early-aborting IO operations, then yes, that's what context is for. However, this doesn't really have anything to do with goroutines, you could do the same if the runtime was built on OS threads.
- kbolino 1y agoGoroutines are preemptive only to the runtime scheduler. You, the application developer merely using the language, cannot directly preempt a goroutine. This makes goroutines effectively cooperative still from the perspective of the developer. The preemptive runtime "just" prevents things like user code starving out the garbage collector. To interrupt a goroutine, your options are generally limited to context cancelation and closing the channel or socket being read, if any. And the goroutine may still refuse to exit (or whatever else you want it to do), though that's largely up to how you code it. This difference is especially stark when compared with Erlang/BEAM where you can directly address, signal, and terminate its lightweight processes.
- schrodinger 1y agoExactly, thank you. I knew that the runtime gained the ability to preempt but the clear fact that you cannot get a handle to a goroutine (eg `gr := go fn()` is proof you have no way to take advantage of this ability as a user.