为什么在 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?


皈依舞
浏览 180回答 2
2回答

月关宝盒

两个问题:不要复制sync.WaitGroup:来自文档:A WaitGroup must not be copied after first use.在开始你的工作之前你需要一个wg.Add(1)- 与wg.Done()wg.Add(1) // <- add thisgo func (wg *sync.WaitGroup ...) { // <- pointer}(&wg, quitSig) // <- pointer to avoid WaitGroup copyhttps://go.dev/play/p/UmeI3TdGvhg

翻阅古今

您正在传递等待组的副本,因此 goroutine 不会影响在外部范围内声明的等待组。通过以下方式修复它:&nbsp; &nbsp; go func(wg *sync.WaitGroup, quitChan, chan struct{}) {&nbsp; &nbsp; &nbsp;...&nbsp; &nbsp; }(&wg, quitSig)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go