It’s channels either way: https://play.golang.org/p/OTNPsxiDSOp

A difference is no access to context.Context.Err(), but in this example the 
error isn’t checked. My opinion is there’s no reason to bring in the whole 
context when all that’s needed is a cancel action. Also there’s an added 
compile check for no writes to the cancel channel this way.

If this is package main then I’m fine with some API leeway, but in a 
library there’s good reason to reduce dependencies, especially on the API.

Matt

On Tuesday, March 20, 2018 at 1:26:36 AM UTC-5, Reinhard Luediger wrote:
>
> Because then you have to deal with all the chennels by yourself. Using the 
> Context API looks for me a bit cleaner and even easier.
>
> Am Montag, 19. März 2018 15:04:17 UTC+1 schrieb matthe...@gmail.com:
>>
>> Only a detail, but why not this instead as the API?
>>
>> func LongRunningTask(cancel <-chan struct{}, index int) (err error) {
>>
>> Matt
>>
>> On Monday, March 19, 2018 at 7:43:19 AM UTC-5, rog wrote:
>>>
>>> Why not something more like this? https://play.golang.org/p/3t4UtoFkoIt 
>>>
>>> A lot of this comes down to what that long running task is doing. 
>>> If it's hard at work doing computational work, the polling approach 
>>> might be appropriate. 
>>> If it's mostly waiting on external events then passing the context 
>>> instance down and selecting 
>>> on the Done channel is probably the way forward. 
>>>
>>> On 19 March 2018 at 07:44, Sathish VJ <sath...@gmail.com> wrote: 
>>> > Looks like this last one works but also quite complicated. 
>>> > 
>>> > One question ... what is the effect of having "default" on line 24 as 
>>> empty? 
>>> > 
>>> > 
>>> > On 18 March 2018 at 14:21, 'Reinhard Luediger' via golang-nuts 
>>> > <golan...@googlegroups.com> wrote: 
>>> >> 
>>> >> I came to the following solution for my long running tasks, using 
>>> >> go-routines & the context package, 
>>> >> 
>>> >> https://play.golang.org/p/2V_29lHt4Wn 
>>> >> 
>>> >> package main 
>>> >> 
>>> >> import ( 
>>> >>    "context" 
>>> >>    "fmt" 
>>> >>    "time" 
>>> >> ) 
>>> >> 
>>> >> //LongRunningTask 
>>> >> func LongRunningTask(ctx context.Context, index int) (err error) { 
>>> >>    // we'll signal on that channel when we finished 
>>> >>    var finished chan struct{} 
>>> >>    fmt.Printf("Starting task %d at: %s\n", index, time.Now()) 
>>> >>    var cancelWork =  make(chan struct{},0) 
>>> >>    go func() { 
>>> >>       workloop: 
>>> >>       for i:= 0 ;i < 10 ;i++{ 
>>> >>          // sleeping for a  long time 
>>> >>          time.Sleep(time.Second * 2) 
>>> >>          select { 
>>> >>          case <-cancelWork: 
>>> >>             fmt.Printf("Canceling work for Index: %d\n",index) 
>>> >>             break workloop 
>>> >>          default: 
>>> >>          } 
>>> >>       } 
>>> >>       finished <- struct{}{} 
>>> >>    }() 
>>> >> 
>>> >>    select { 
>>> >>    // when the task finished normal we'll get a notification on the 
>>> >> finished channel 
>>> >>    case <-finished: 
>>> >>       fmt.Printf("Task %d  finished at:%s\n", index, time.Now()) 
>>> >>       return nil 
>>> >> 
>>> >>    // If the context gets canceled we receive a signal on that 
>>> channel 
>>> >>    case <-ctx.Done(): 
>>> >>       err := ctx.Err() 
>>> >>       _=err 
>>> >>       //the context.Err() method gives us the reason why it was 
>>> canceled 
>>> >>       fmt.Printf("task %d aborted reason:%s at: %s\n", index, 
>>> ctx.Err(), 
>>> >> time.Now()) 
>>> >>       cancelWork <- struct{}{} 
>>> >>       return ctx.Err() 
>>> >>    } 
>>> >> 
>>> >> } 
>>> >> 
>>> >> func main() { 
>>> >>    var ctx context.Context 
>>> >> 
>>> >>    // get a new Context and  the corresponding cancel function 
>>> >>    ctx, cancel := context.WithCancel(context.Background()) 
>>> >> 
>>> >>    // create a new context with a timeout value of 4 Seconds derived 
>>> from 
>>> >> the context above 
>>> >>    ctx, _ = context.WithTimeout(ctx, time.Second*4) 
>>> >> 
>>> >>    // Sleeping for one Second to clarify that the timeout is running 
>>> from 
>>> >> the point where it is created 
>>> >>    time.Sleep(time.Second * 1) 
>>> >> 
>>> >>    fmt.Printf("Starting background tasks time %s", time.Now()) 
>>> >>    for i := 0; i < 7; i++ { 
>>> >>       go LongRunningTask(ctx, i) 
>>> >> 
>>> >>    } 
>>> >> 
>>> >>    // if we sllep longer than the timeout we'll see that the tasks 
>>> will be 
>>> >> canceled after timeout 
>>> >>    time.Sleep(time.Second * 8) 
>>> >> 
>>> >>    // The call of the cancel function has only effect when we slept 
>>> >> shorter then the defined timeout 
>>> >>    // if so the single call of the cancel function will send a 
>>> >> cancellation information to all child context 
>>> >>    cancel() 
>>> >> 
>>> >>    // Sleep a while to see the cancellation messages 
>>> >>    time.Sleep(time.Second * 4) 
>>> >> 
>>> >> } 
>>> >> 
>>> >> 
>>> >> Am Freitag, 16. März 2018 15:45:00 UTC+1 schrieb Sathish VJ: 
>>> >>> 
>>> >>> All the examples I've seen use some kind of ticker to run various 
>>> cases 
>>> >>> of a select statement.  But how does one run a long running task 
>>> that is 
>>> >>> still cancelable? 
>>> >>> 
>>> >>> 
>>> >>> In the example below the quit part is never reached. 
>>> >>> 
>>> >>> https://play.golang.org/p/PLGwrUvKaqn  (it does not run properly on 
>>> >>> play.golang.org). 
>>> >>> 
>>> >>> package main 
>>> >>> 
>>> >>> 
>>> >>> import ( 
>>> >>>  "fmt" 
>>> >>>  "os" 
>>> >>>  "time" 
>>> >>> ) 
>>> >>> 
>>> >>> 
>>> >>> func f(quit chan bool) { 
>>> >>>  for { 
>>> >>>    select { 
>>> >>>    case <-time.After(0 * time.Second): 
>>> >>>      // start long running task immediately. 
>>> >>>      for { 
>>> >>>        time.Sleep(500 * time.Millisecond) 
>>> >>>        fmt.Printf(". ") 
>>> >>>      } 
>>> >>>    case <-quit: 
>>> >>>      fmt.Println("quit called") 
>>> >>>      //deallocate resources in other long running task and then 
>>> return 
>>> >>> from function. 
>>> >>>      os.Exit(0) // or return 
>>> >>>    } 
>>> >>>  } 
>>> >>> } 
>>> >>> 
>>> >>> 
>>> >>> func main() { 
>>> >>>  var quit chan bool 
>>> >>>  go f(quit) 
>>> >>> 
>>> >>> 
>>> >>>  println("quit sending ... ") 
>>> >>>  quit <- true 
>>> >>>  println("after quit sent") 
>>> >>> 
>>> >>> 
>>> >>>  var i chan int 
>>> >>>  <-i 
>>> >>> } 
>>> >>> 
>>> >>> 
>>> >> -- 
>>> >> You received this message because you are subscribed to a topic in 
>>> the 
>>> >> Google Groups "golang-nuts" group. 
>>> >> To unsubscribe from this topic, visit 
>>> >> https://groups.google.com/d/topic/golang-nuts/l2A0PS91T0A/unsubscribe. 
>>>
>>> >> To unsubscribe from this group and all its topics, send an email to 
>>> >> golang-nuts...@googlegroups.com. 
>>> >> For more options, visit https://groups.google.com/d/optout. 
>>> > 
>>> > 
>>> > -- 
>>> > 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...@googlegroups.com. 
>>> > For more options, visit https://groups.google.com/d/optout. 
>>>
>>

-- 
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.
For more options, visit https://groups.google.com/d/optout.

Reply via email to