context.WithDeadline 同时传递上下文去例程?

context.WithDeadline while passing context to go routine?

context.WithDeadline 同时将上下文传递给 go routine?

我整理了一些示例代码,它们将为我的切片中的每个项目启动一个新的 goroutine。 目前,这将等待 done 通道被调用 len(slice) 次。

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

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

我已经阅读了 godoc 和 Go Concurrency Patterns: Context (on the go blog) 但是作为一个新的 gopher, 我 none 更聪明。我发现的许多例子都使用 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!")

}

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

设置上下文后,您可以在 Context.Done() 频道上 select 确定它何时过期。

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 而不是依赖通道上的令牌计数,并使用 defer 来调用 Done。