为什么在 go test 中使用 WaitGroup.Wait() 时会挂起?
这是我的意思的一个简单示例
package main
import (
"sync"
"testing"
"time"
)
func TestWaitGroup(t *testing.T) {
var wg sync.WaitGroup
quitSig := make(chan struct{})
go func(wg sync.WaitGroup, quitChan, chan struct{}) {
defer func() {
t.Log("Done...")
wg.Done()
t.Log("Done!")
}()
t.Log("waiting for quit channel signal...")
<-quitChan
t.Log("signal received")
}(wg, quitSig)
time.Sleep(5*time.Second)
t.Log("Done sleeping")
close(quitSig)
t.Log("closed quit signal channel")
wg.Wait()
t.Log("goroutine shutdown")
}
当我运行它时,我得到以下内容
=== RUN TestWaitGroup
main.go:18: waiting for quit channel signal...
main.go:23: Done sleeping
main.go:25: closed quit signal channel
main.go:20: signal received
main.go:14: Done...
main.go:16: Done!
它只是挂起直到超时。如果您只是defer wg.Done()
,则会观察到相同的行为。我正在运行 go1.18
。这是一个错误还是我在这种情况下没有正确使用 WaitGroups ?
Here's a simple example of what I mean
package main
import (
"sync"
"testing"
"time"
)
func TestWaitGroup(t *testing.T) {
var wg sync.WaitGroup
quitSig := make(chan struct{})
go func(wg sync.WaitGroup, quitChan, chan struct{}) {
defer func() {
t.Log("Done...")
wg.Done()
t.Log("Done!")
}()
t.Log("waiting for quit channel signal...")
<-quitChan
t.Log("signal received")
}(wg, quitSig)
time.Sleep(5*time.Second)
t.Log("Done sleeping")
close(quitSig)
t.Log("closed quit signal channel")
wg.Wait()
t.Log("goroutine shutdown")
}
When I run this, I get the following
=== RUN TestWaitGroup
main.go:18: waiting for quit channel signal...
main.go:23: Done sleeping
main.go:25: closed quit signal channel
main.go:20: signal received
main.go:14: Done...
main.go:16: Done!
Where it just hangs until it timesout. If you just do defer wg.Done()
the same behaviour is observed. I'm running go1.18
. Is this a bug or am I using not using WaitGroups properly in this context?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
两个问题:
不要复制
sync.WaitGroup
:来自文档:首次使用后不得复制 WaitGroup。
在启动工作之前,您需要一个
wg.Add(1)
- 与wg.Done 配对()
https://go.dev/play/p/UmeI3TdGvhg
Two issues:
don't copy
sync.WaitGroup
: from the docs:A WaitGroup must not be copied after first use.
you need a
wg.Add(1)
before launching your work - to pair with thewg.Done()
https://go.dev/play/p/UmeI3TdGvhg
您正在传递候补组的副本,因此Goroutine不会影响外部范围中声明的候补群。修复它:
You are passing a copy of the waitgroup, so the goroutine does not affect the waitgroup declared in the outer scope. Fix it by: