为什么 WaitGroup.Wait() 在与 go test 一起使用时会挂起?
Why is WaitGroup.Wait() hanging when using it with go test?
这是我的意思的一个简单例子
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?
您正在传递等待组的副本,因此 goroutine 不会影响在外部作用域中声明的等待组。通过以下方式修复:
go func(wg *sync.WaitGroup, quitChan, chan struct{}) {
...
}(&wg, quitSig)
两期:
不要复制 sync.WaitGroup
: 来自 docs:
A WaitGroup must not be copied after first use.
您需要 wg.Add(1)
才能开始您的工作 - 与 wg.Done()
配对
wg.Add(1) // <- add this
go func (wg *sync.WaitGroup ...) { // <- pointer
}(&wg, quitSig) // <- pointer to avoid WaitGroup copy
这是我的意思的一个简单例子
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?
您正在传递等待组的副本,因此 goroutine 不会影响在外部作用域中声明的等待组。通过以下方式修复:
go func(wg *sync.WaitGroup, quitChan, chan struct{}) {
...
}(&wg, quitSig)
两期:
不要复制
sync.WaitGroup
: 来自 docs:A WaitGroup must not be copied after first use.
您需要
配对wg.Add(1)
才能开始您的工作 - 与wg.Done()
wg.Add(1) // <- add this
go func (wg *sync.WaitGroup ...) { // <- pointer
}(&wg, quitSig) // <- pointer to avoid WaitGroup copy