On Wed, Jan 12, 2022 at 3:01 AM E Z <legend...@gmail.com> wrote: > Thank you very much. > > I understand that we can use context.Context to resolve the network > blocking problem in long-running function if the network library support > passing a context parameter. > > But for the CPU-bound code, Is the following implementation mentioned by > axel the only way to make a function exit earlier? >
It's not the only way, but it's the way I'd generally recommend. Universally using `context.Context` to signal cancellation solves exactly the problem you where having. Specifically, > The above code is executing in a goroutine, if I want to cancel this goroutine, I can send a signal to task.channel, but the signal only can be retrieved after the task.task.Run is finished, it may be a long time, such as 5 mins. If `task.task.Run` takes a `context.Context`, it can exit sooner than after 5 minutes. If it takes that long because it does remote requests, it can propagate the Context itself. If it is CPU-bound, it can check if the Context was cancelled, say, every 1000 iterations (or whatever. What's a reasonable number depends heavily on what it's doing). But, yes, for such a CPU-bound task, actively checking if it was cancelled via a mechanism like a Context is the only way to be aborted. For example, goroutine is executing a task to update a DNS record and then > wait some time until the DNS record takes effect in some name servers. It > may take some seconds even minutes to make the DNS record take effect in > the name server. > To be clear, this is not a CPU-bound process. Updating the DNS record is either a network request/IPC. The waiting is then a loop like for { select { case <-ctx.Done(): return ctx.Err() case <-time.After(time.Second()): // simplistic, you'd likely want some jitter and/or exponential backoff here if recordHasChanged(ctx) { // network request to check if the DNS record has changed - takes a Context, as it's a network request return nil } } } This will spend most of its time sleeping. A CPU-bound task is something like a diff-operation, which is just an algorithm that can be very slow for large inputs, just because it has a lot of work to churn through. In this case, seems I can't cancel the running goroutine except that we add > the above select at every for loop or wait timer, or I change the design > to split these time-consuming operations into different goroutine. Both > seem not so good. > I don't understand why you think this is not good. It seems perfectly reasonable code. But yes, it's what you have to do. Go has no way to asynchronously stop code, you need to manually cancel. And context.Context gives a universal mechanism to do that, which I would recommend using for that. > > On Tuesday, January 11, 2022 at 1:04:15 PM UTC-8 Ian Lance Taylor wrote: > >> On Tue, Jan 11, 2022 at 12:15 PM 'Axel Wagner' via golang-nuts >> <golan...@googlegroups.com> wrote: >> > >> > The best way to do this is to plumb a context.Context through all >> long-running functions - in particular, anything talking to the network. >> > Most RPC and network frameworks provide a way to pass a Context, so >> consistently doing this will more or less transparently cancel your >> business logic ASAP. >> > For purely CPU bound code, this is a bit more awkward, because you >> indeed have to intersperse code like >> > select { >> > case <-ctx.Done(): >> > return ctx.Err() >> > default: >> > } >> > to make the code return early. But that should be relatively rare. >> >> Yes. See also https://go.dev/blog/context . >> >> Ian >> > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/d1898f67-d1e0-4276-af92-016b82866de4n%40googlegroups.com > <https://groups.google.com/d/msgid/golang-nuts/d1898f67-d1e0-4276-af92-016b82866de4n%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAEkBMfG-ucbuosT25i%2Bbpd81EQp-mj_wksgHumgQxbgRfrgsfQ%40mail.gmail.com.