context.WithDeadline在传递上下文时去常规吗?

时间:2017-03-24 14:26:19

标签: go concurrency goroutine

context.WithDeadline在传递上下文时去常规吗?

我已经整理了一些示例代码,这些代码将为切片中的每个项目启动一个新的goroutine。 此时,这将等待完成通道被称为len(切片)次。

但是,我还想在goroutines中实现事件泄漏的超时。 似乎context.WithDeadline(或者可能是WithTimeout?)是要使用的适当函数。

例如,假设我想为从main()初始化的所有goroutine传递23秒的截止日期。 但是,我不清楚我应该怎么做。

我和Go Concurrency Patterns: Context (on the go blog)一起读过godoc,但作为一个新的地鼠, 我不是更聪明的人。我发现的许多例子都使用http.handler(或类似的例子,所以它们对我来说是一些混乱的来源。

在此处传递带截止/超时的上下文的适当方法是什么。

package main

import (
  "fmt"
  "time"
)

func sleepNow(i int, done chan bool) {
  time.Sleep(time.Duration(i) * time.Second)
  fmt.Println(i, "has just woken up from sleep and the time is", time.Now())

  done <- true
}

func main() {
  done := make(chan bool)
  numbersSlice := []int{10, 20, 30, 12}

  for _, v := range(numbersSlice){
    go sleepNow(v, done)
  }

  for x := 0; x < len(numbersSlice); x++ {
  <-done
  }
  fmt.Println("Looks like we are all done here!")

}

1 个答案:

答案 0 :(得分:3)

您需要做的就是将上下文放入要使用它的函数中。在很多情况下,您可以使用简单的闭包,或者在这种情况下,将其添加到函数参数中。

准备好上下文后,您可以在Context.Done()频道上进行选择,以确定其过期时间。

https://play.golang.org/p/q-n_2mIW2X

func sleepNow(i int, ctx context.Context, wg *sync.WaitGroup) {
    defer wg.Done()

    select {
    case <-time.After(time.Duration(i) * time.Second):
        fmt.Println(i, "has just woken up from sleep and the time is", time.Now())
    case <-ctx.Done():
        fmt.Println(i, "has just been canceled")
    }
}

func main() {
    var wg sync.WaitGroup
    numbersSlice := []int{1, 5, 4, 2}

    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)

    for _, v := range numbersSlice {
        wg.Add(1)
        go sleepNow(v, ctx, &wg)
    }

    wg.Wait()
    cancel()

    fmt.Println("Looks like we are all done here!")
}

您还应该使用sync.WaitGroup而不是依靠通过频道计算令牌,并使用延迟来调用完成。