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测试不会报告错误,并且将始终运行。 在咨询了很多信息之后,我没有找到解释这种现象的答案。也许我的方法是错误的?此通道方法用于项目中。 谢谢。
答案 0 :(得分:1)
运行常规程序时,它将等待通道的输入。而且,由于只有一个goroutine,因此无法从通道接收输入(没有其他线程可以发送给它)。因此报告了死锁。
另一方面,测试运行程序使用goroutines执行测试。因此,产生了一个以上的goroutine,并且没有检测到死锁(运行时假定其他goroutine可以发送到通道)。
从评论中回答您的问题:运行和测试不应达到相同的效果。 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()
}