将超时设置为WaitGroup.Wait()的惯用方式是什么?

我之所以想这么做,是为了保护我的"调度程序"不可能永远等待一个错误的"工作人员".这就引出了一些哲学问题(例如,一旦系统中出现了错误的工作人员,该系统如何可靠地继续工作?),但我认为这超出了这个问题的范围.

我会提供一个答案.现在我已经把它写下来了,它看起来并没有那么糟糕,但它仍然感觉比它应该的更复杂.我想知道是否有更简单、更惯用的方法,或者甚至是一种不使用waitgroup的替代方法.

好的.

推荐答案

大多数情况下,您发布的below个解决方案都是最好的解决方案.改善它的几个小贴士:

  • 或者,您可以关闭通道以发出完成信号,而不是在其上发送值,即在关闭的通道can always proceed immediately上执行接收操作.
  • 最好使用defer语句来表示完成,即使函数突然终止,它也会执行.
  • 此外,如果只有一个"作业(job)"需要等待,则可以完全省略WaitGroup,只发送一个值,或在作业(job)完成时关闭通道(与select语句中使用的通道相同).
  • 指定1秒的持续时间非常简单,只需:timeout := time.Second.例如,指定2秒为:timeout := 2 * time.Second.您不需要转换,time.Second已经是time.Duration类型,将其乘以像2这样的无类型常量也会得到time.Duration类型的值.

我还将创建一个包装此功能的助手/实用程序函数.请注意,必须将WaitGroup作为指针传递,否则副本将不会收到WaitGroup.Done()次调用的"通知".比如:

// waitTimeout waits for the waitgroup for the specified max timeout.
// Returns true if waiting timed out.
func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {
    c := make(chan struct{})
    go func() {
        defer close(c)
        wg.Wait()
    }()
    select {
    case <-c:
        return false // completed normally
    case <-time.After(timeout):
        return true // timed out
    }
}

使用它:

if waitTimeout(&wg, time.Second) {
    fmt.Println("Timed out waiting for wait group")
} else {
    fmt.Println("Wait group finished")
}

Go Playground号公路上试试吧.

Go相关问答推荐

如何在定制普罗米修斯出口商中测试动态计量注册?

Term~T中的类型不能是类型参数,但可以是引用类型参数的切片

读取JSON数据并在网页上显示

租户GUID X的租户不存在self 邮箱帐户的租户(我是唯一的成员)

允许在 struct 中使用复合作为函数参数

Go SQLCMD比Windows本机版本慢吗?

GO框架Echo中间件的使用

如何解析Go-Gin多部分请求中的 struct 切片

可以';t从主机连接到ScyllaDB容器

「GORM错误」不支持的数据类型:&[],不正确的模式

如何将 DirName 和 serial 添加到 X509v3 Authority Key Identifier

如何使用 sync.WaitGroup 来执行所有的 goroutine?

对 CSV 进行单元测试失败

Apache Beam 在 Go 中从 PCollection 中 Select 前 N 行

使用 Grafana alert 在几分钟内重复alert

使用图像解码 JPEG 时 colored颜色 不正确.解码并写入 PDF?

如何模仿联合类型

如何使用struct的方法清除除某些字段之外的struct值

如何在 golang 中同时加载 .env 文件和 os 环境变量

使用正则表达式拆分具有相同标题的数据块