Golang WaitGroup Timeout错误处理

时间:2017-10-01 06:57:10

标签: go

在下面的代码中,如果其中一个启动的go例程花费太长时间(例如> 10秒)来完成,我该如何添加正确的超时错误处理?请注意,我不希望每个例行程序都有一个“整体”超时但是超时,因此我也可以知道在我的错误报告中哪个例行程序超时。

var wg sync.WaitGroup

for _, element:= range elements{
    wg.Add(1)
    go doWork(element, &wg)
}
wg.Wait()

亲切的问候

3 个答案:

答案 0 :(得分:2)

很好的方法是使用context.WithDeadline

// WithDeadline returns a copy of the parent context with the deadline adjusted
// to be no later than d. If the parent's deadline is already earlier than d,
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
// context's Done channel is closed when the deadline expires, when the returned
// cancel function is called, or when the parent context's Done channel is
// closed, whichever happens first.
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete.
package main

import (
    "context"
    "fmt"
    "time"
)

func main() {
    ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(100*time.Millisecond))

    // Even though ctx will be expired, it is good practice to call its
    // cancelation function in any case. Failure to do so may keep the
    // context and its parent alive longer than necessary.
    defer cancel()

    select {
    case <-time.After(1 * time.Second):
        fmt.Println("overslept")
    case <-ctx.Done():
        fmt.Println(ctx.Err())
    }

}

答案 1 :(得分:1)

我确实遇到了同样的问题并提出了这种方法:

https://play.golang.org/p/9F9T_sYIof

使用:c = b.stack().to_frame(a.index[0]).T.reindex(a.index, method='ffill') print (c) A B C 3 4 5 3 4 5 3 4 5 2010-01-29 1 1 1 1 1 1 1 1 1 2010-02-26 1 1 1 1 1 1 1 1 1 2010-03-31 1 1 1 1 1 1 1 1 1 2010-04-30 1 1 1 1 1 1 1 1 1 2010-05-31 1 1 1 1 1 1 1 1 1 2010-06-30 1 1 1 1 1 1 1 1 1 2010-07-30 1 1 1 1 1 1 1 1 1 2010-08-31 1 1 1 1 1 1 1 1 1 2010-09-30 1 1 1 1 1 1 1 1 1 2010-10-29 1 1 1 1 1 1 1 1 1 2010-11-30 1 1 1 1 1 1 1 1 1 2010-12-31 1 1 1 1 1 1 1 1 1 d = pd.concat([a,c], axis=1).sort_index(axis=1) print (d) A B C 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 2010-01-29 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1 2010-02-26 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1 2010-03-31 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1 2010-04-30 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1 2010-05-31 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1 2010-06-30 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1 2010-07-30 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1 2010-08-31 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1 2010-09-30 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1 2010-10-29 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1 2010-11-30 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1 2010-12-31 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1

https://play.golang.org/p/WK0ebe0c9t

不知道这样做是否正确,但是有效:

context.WithTimeout(context.Background(), 10*time.Second)

注意package main import ( "context" "fmt" "sync" "time" ) func doWork(element int, wg *sync.WaitGroup) { ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(10*time.Second)) defer cancel() ch := make(chan struct{}) go func(ch chan struct{}) { time.Sleep(time.Second) fmt.Printf("element = %+v\n", element) ch <- struct{}{} }(ch) select { case <-ch: case <-ctx.Done(): fmt.Println(ctx.Err()) } wg.Done() } func main() { var wg sync.WaitGroup elements := []int{1, 2, 3} for _, element := range elements { wg.Add(1) go doWork(element, &wg) } wg.Wait() } 函数中的goroutine:

doWork

这是我不知道是否是最佳方式的部分,但似乎是在使用上下文时主要想要处理go func(ch chan struct{}) { // your code logic goes here }(ch)

时要遵循的模式

答案 2 :(得分:0)

您可以通过以下方式使用Context

func doWork(ctx context.Context, element Element, wg &sync.WaitGroup) {
    defer wg.Done()

    done := make(chan struct{})
    go func() {
       // do some work on element
       done <- struct{}{} // signal work is done
    }

    select {
       case <- done: 
       { 
          // work completed in time
       }
       case <- ctx.Done:
       {
         // timeout reached
       }
    }
}

contexts := make([]*context.Context, len(elements))

for _, element:= range elements{
    wg.Add(1)
    ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
    defer cancel()
    contexts = append(contexts, ctx)
    go doWork(ctx, element, &wg)
}
wg.Wait()

for i, ctx := range contexts {
  if ctx.Err() {
     fmt.Println("Go routine ", i, "canceled due to", ctx.Err())
  }
}