gogoroutinego-testing

How test functions are called in Go?


I'm studying Go language and I have a question now.

I was just testing buffered and unbuffered channels.

While writing the test code for it, a situation occurred that I couldn't understand the result.

func BenchmarkUnbufferedChannelInt(b *testing.B) {
    ch := make(chan int)
    go func() {
        for i := 0; i < b.N; i++ {
            ch <- i
        }
    }()

    for {
        <-ch
    }
}

The above code doesn't stop, because <-ch makes the goroutine blocked forever. However, the code below does not create an blocked status and the testing succeeds.

func BenchmarkUnbufferedChannelInt(b *testing.B) {
    ch := make(chan int)
    go func() {
        for {
            <-ch
        }
    }()

    for i := 0; i < b.N; i++ {
        ch <- i
    }
}
BenchmarkUnbufferedChannelInt
BenchmarkUnbufferedChannelInt-12         8158381               142.1 ns/op
PASS

As far as I know, there is no parent-child relationship between goroutines, so the termination of one goroutine does not affect the termination of the other goroutines except for main goroutine.

Theoretically, both of the above codes should eventually be blocked forever.

But I don't know why only the second code succeeds.

I wonder how Go calls test functions. Assuming that the goroutine where the test function runs has the same characteristics as the main goroutine, I can understand the result of the above codes.

But if not, I don't understand. In both tests, a goroutine should eventually be blocked forever.

Can you explain the above result? please!


Solution

  • The above code doesn't stop, because <-ch makes the goroutine blocked forever.

    No, it's being blocked because of the infinite for loop.

    However, the code below does not create an blocked status and the testing succeeds.

    Right, because the for loop runs for as many loops as you want your benchmark to run. Once this loop ends, the goroutine you spun up is forgotten and you have a leak. See https://www.ardanlabs.com/blog/2018/11/goroutine-leaks-the-forgotten-sender.html: If you start a Goroutine that you expect to eventually terminate but it never does then it has leaked.