go test 和 go run 执行以下通道代码,但结果不同。为什么?

main.go


func main() {

    fmt.Println("hello")

    ch := make(chan struct{}, 1)

    <-ch

}

main_test.go


func Test_Main(t *testing.T) {

    main()

}

去运行 main.go


  hello

  fatal error: all goroutines are asleep - deadlock!

  goroutine 1 [chan receive]:

  main.main()

但是去测试 -v main_test.go -run=Test_Main


=== RUN   Test_Main

hello


go test 不会报错,会一直运行。查阅了很多资料,也没有找到解释这个现象的答案。可能是我的方式不对?这个通道方式是在项目中使用的。谢谢。


慕工程0101907
浏览 166回答 1
1回答

摇曳的蔷薇

当您运行常规程序时,它会等待来自通道的输入。而且因为只有一个 goroutine,所以无法从通道接收输入(没有其他线程可以发送给它)。因此报告了死锁。另一方面,测试运行器使用 goroutines 来执行测试。所以产生了不止一个 goroutine 并且没有检测到死锁(运行时假设其他 goroutine 可以发送到通道)。从评论中回答您的问题: go run 和 go test 不应该达到相同的效果。go run 执行你的程序, go test 执行测试你的代码的程序。这些命令执行两个不同的程序。我不确定您是否可以通过测试检测到这种错误(死锁)。编辑: go test等待测试完成(您可以使用-timeout d选项配置多长时间)。所以我假设它产生了等待timer.Timer过期的 goroutine,所以没有死锁(总是有一个 goroutine 有机会被执行)。Edit2: 试试这个程序:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "time")func main() {&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; t := time.NewTimer(10 * time.Second)&nbsp; &nbsp; &nbsp; &nbsp; <-t.C&nbsp; &nbsp; }()&nbsp; &nbsp; fmt.Println("hello")&nbsp; &nbsp; ch := make(chan struct{}, 1)&nbsp; &nbsp; <-ch}它在报告死锁之前等待 10 秒。Edit3: 或者看一下说明测试运行器如何工作的流动代码:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "time")func original_main_func() {&nbsp; &nbsp; fmt.Println("hello")&nbsp; &nbsp; ch := make(chan struct{}, 1)&nbsp; &nbsp; <-ch}func test() {&nbsp; &nbsp; original_main_func()}func test_runner() {&nbsp; &nbsp; ch := make(chan struct{}, 1)&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; test()&nbsp; &nbsp; &nbsp; &nbsp; close(ch)&nbsp; &nbsp; }()&nbsp; &nbsp; t := time.NewTimer(10 * time.Second)&nbsp; &nbsp; select {&nbsp; &nbsp; case <-t.C:&nbsp; &nbsp; &nbsp; &nbsp; panic("timeout")&nbsp; &nbsp; case <-ch:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("test executed")&nbsp; &nbsp; }}func main() {&nbsp; &nbsp; test_runner()}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go