3

我在使用频道进行测试时遇到了一个奇怪的问题。

在正常的main函数中,下面的代码会报死锁错误。

package main

import (
    "fmt"
)

func main() {
    c := make(chan int)
    c <- 1
    fmt.Println(<-c)
}

但是在我的机器上,这个简单的测试似乎永远陷入僵局或阻塞,或者由于我不知道的任何原因而无法退出。我在 Emacs 和终端中都调用了测试,得到了相同的结果。命令是go test -run TestChan\$ . -v -count=1。我尝试了一个更简单的命令(go test -run TestChan),但仍然得到相同的结果。我在 Go 操场上尝试过(这里),它报告了死锁错误。我的 Go 环境有问题吗?

package main

import (
    "fmt"
    "testing"
)

func TestChan(t *testing.T) {
    c := make(chan int)
    c <- 1
    fmt.Println(<-c)
}

-------------------------------------------------- --------------------------------------------------

更新

看来我的问题没有说清楚。情况是:相同的测试在我的机器和 Go 操场上表现不同。现在我设置-timeout 5s了,但错误信息与 Go 操场上的不同。我发现与本地不同的另一件事是测试运行程序似乎与我本地不同。它在包装之下go-faketime

本地输出

$ go test main_test.go -timeout 5s
panic: test timed out after 5s

goroutine 17 [running]:
testing.(*M).startAlarm.func1()
    /usr/local/go/src/testing/testing.go:1460 +0xdf
created by time.goFunc
    /usr/local/go/src/time/sleep.go:168 +0x44

goroutine 1 [chan receive]:
testing.(*T).Run(0xc000108120, 0x1141975, 0x8, 0x114a528, 0x1075a96)
    /usr/local/go/src/testing/testing.go:1044 +0x37e
testing.runTests.func1(0xc000108000)
    /usr/local/go/src/testing/testing.go:1285 +0x78
testing.tRunner(0xc000108000, 0xc000066e10)
    /usr/local/go/src/testing/testing.go:992 +0xdc
testing.runTests(0xc00000c060, 0x1236220, 0x1, 0x1, 0x0)
    /usr/local/go/src/testing/testing.go:1283 +0x2a7
testing.(*M).Run(0xc000106000, 0x0)
    /usr/local/go/src/testing/testing.go:1200 +0x15f
main.main()
    _testmain.go:44 +0x135

goroutine 6 [chan send]:
command-line-arguments.TestChan(0xc000108120)
    /Users/james/prog/allez/mtest/main_test.go:10 +0x59
testing.tRunner(0xc000108120, 0x114a528)
    /usr/local/go/src/testing/testing.go:992 +0xdc
created by testing.(*T).Run
    /usr/local/go/src/testing/testing.go:1043 +0x357
FAIL    command-line-arguments  5.013s
FAIL

去游乐场输出

=== RUN   TestChan
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
testing.(*T).Run(0xc00011a120, 0x4f71c0, 0x8, 0x4ff688, 0x498336)
    /usr/local/go-faketime/src/testing/testing.go:1043 +0x37e
testing.runTests.func1(0xc00011a000)
    /usr/local/go-faketime/src/testing/testing.go:1284 +0x78
testing.tRunner(0xc00011a000, 0xc000066df8)
    /usr/local/go-faketime/src/testing/testing.go:991 +0xdc
testing.runTests(0xc00010c040, 0xc00010c020, 0x1, 0x1, 0x0)
    /usr/local/go-faketime/src/testing/testing.go:1282 +0x2a7
testing.(*M).Run(0xc000118000, 0x0)
    /usr/local/go-faketime/src/testing/testing.go:1199 +0x15f
testing.Main(0x4ff690, 0xc00010c020, 0x1, 0x1, 0x0, 0x0, 0x0, 0x5e8860, 0x0, 0x0)
    /usr/local/go-faketime/src/testing/testing.go:1126 +0xd4
main.main()
    /tmp/sandbox970213620/prog.go:24 +0x9c

goroutine 18 [chan send]:
main.TestChan(0xc00011a120)
    /tmp/sandbox970213620/prog.go:10 +0x59
testing.tRunner(0xc00011a120, 0x4ff688)
    /usr/local/go-faketime/src/testing/testing.go:991 +0xdc
created by testing.(*T).Run
    /usr/local/go-faketime/src/testing/testing.go:1042 +0x357

我的问题是

  • 为什么 Go 测试阻塞通道不报告死锁?
  • 如果它是按设计工作的(因为同时还有其他 goroutines 运行),那么 Go 游乐场中的相同测试如何报告相同的错误消息,就好像代码在 main func 中运行一样?(这个问题从 Go 频道的领域发散到 Go Playground 如何处理测试)
4

0 回答 0