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

标签 go concurrency goroutine

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

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

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

例如,假设我想为所有从 main() 初始化的 goroutine 传递 23 秒的截止日期。 但是,我不清楚应该如何执行此操作。

我已经阅读了 godoc 和 Go Concurrency Patterns: Context (on the go blog)但作为一只新的地鼠, 我一点也不聪明。我发现的许多示例都使用了 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() channel 上进行选择以确定它何时过期。

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

关于go - context.WithDeadline 同时传递上下文去例程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43002046/

相关文章:

amazon-web-services - 通过 Go SDK 的 Lambda@Edge

multithreading - 如何等待执行

methods - 如何获取并发方法

go - 如何在函数之间传递带有chan的变量

sql-server - 什么样的SQL-Server锁级别适合insert?

docker - 在导出的 golang 变量中声明的正在运行的 docker 容器的最新列表

go - 为什么我不能 append 到作为 golang 结构属性的 slice ?

email - 包含 html 内容的邮件显示换行符或忽略换行符

go - VS Code Go扩展无法加载,因为无法更改go.mod?

mysql - 使用文件系统与 RDMBS (MySQL) 的并发处理