登录
首页 >  Golang >  Go问答

为什么 go test 和 go run 在执行以下通道代码时产生不同的结果?

来源:stackoverflow

时间:2024-02-21 22:48:30 378浏览 收藏

大家好,今天本人给大家带来文章《为什么 go test 和 go run 在执行以下通道代码时产生不同的结果?》,文中内容主要涉及到,如果你对Golang方面的知识点感兴趣,那就请各位朋友继续看下去吧~希望能真正帮到你们,谢谢!

问题内容

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()

但是 go test -v main_test.go -run=test_main

=== RUN   Test_Main
hello

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


解决方案


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

另一方面,测试运行器使用 goroutine 来执行测试。因此,生成了多个 goroutine,并且未检测到死锁(运行时假设其他 goroutine 可以发送到通道)。

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

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

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

编辑2: 试试这个程序:

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 秒。

编辑3: 或者看一下说明测试运行程序如何工作的流动代码:

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()
}

好了,本文到此结束,带大家了解了《为什么 go test 和 go run 在执行以下通道代码时产生不同的结果?》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多Golang知识!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>