为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕工程0101907 2022-05-18 15:39:20
main.gofunc main() {    fmt.Println("hello")    ch := make(chan struct{}, 1)    <-ch}main_test.gofunc 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_Mainhellogo test 不会报错,会一直运行。查阅了很多资料,也没有找到解释这个现象的答案。可能是我的方式不对?这个通道方式是在项目中使用的。谢谢。
查看完整描述

1 回答

?
摇曳的蔷薇

TA贡献1793条经验 获得超6个赞

当您运行常规程序时,它会等待来自通道的输入。而且因为只有一个 goroutine,所以无法从通道接收输入(没有其他线程可以发送给它)。因此报告了死锁。


另一方面,测试运行器使用 goroutines 来执行测试。所以产生了不止一个 goroutine 并且没有检测到死锁(运行时假设其他 goroutine 可以发送到通道)。


从评论中回答您的问题: go run 和 go test 不应该达到相同的效果。go run 执行你的程序, go test 执行测试你的代码的程序。这些命令执行两个不同的程序。


我不确定您是否可以通过测试检测到这种错误(死锁)。


编辑: go test等待测试完成(您可以使用-timeout d选项配置多长时间)。所以我假设它产生了等待timer.Timer过期的 goroutine,所以没有死锁(总是有一个 goroutine 有机会被执行)。


Edit2: 试试这个程序:


package main


import (

    "fmt"

    "time"

)


func main() {

    go func() {

        t := time.NewTimer(10 * time.Second)

        <-t.C

    }()

    fmt.Println("hello")

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

    <-ch

}

它在报告死锁之前等待 10 秒。


Edit3: 或者看一下说明测试运行器如何工作的流动代码:


package main


import (

    "fmt"

    "time"

)


func original_main_func() {

    fmt.Println("hello")

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

    <-ch

}


func test() {

    original_main_func()

}


func test_runner() {

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

    go func() {

        test()

        close(ch)

    }()

    t := time.NewTimer(10 * time.Second)

    select {

    case <-t.C:

        panic("timeout")

    case <-ch:

        fmt.Println("test executed")

    }

}


func main() {

    test_runner()

}


查看完整回答
反对 回复 2022-05-18
  • 1 回答
  • 0 关注
  • 165 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号