我正在尝试实现一个非常简单的测试函数来验证来自我的Euler问题解决方案的结果。
在下面的代码中,我创建了一个切片映射,在索引0上,我调用返回整数的函数,并在索引1上调用我期望从该函数得到的结果。
package euler
import "testing"
func TestEulers(t *testing.T) {
tests := map[string][]int{
"Euler1": {Euler1(), 233168},
"Euler2": {Euler2(), 4613732},
"Euler3": {Euler3(), 6857},
"Euler4": {Euler4(), 906609},
"Euler5": {Euler5(), 232792560},
"Euler6": {Euler6(), 25164150},
}
for key, value := range tests {
if value[0] != value[1] {
t.Errorf("%s\nExpected: %d\nGot:%d",
key, value[0], value[1])
}
}
}
对于该地图,每个功能正常并返回我期望的结果如果我一个接一个地运行,或者如果我发表评论,那么就说,这些键的一半部分/值。
例如,如果我使用这些行调用上面的函数,则测试将通过。
tests := map[string][]int{
"Euler1": {Euler1(), 233168},
// "Euler2": {Euler2(), 4613732},
"Euler3": {Euler3(), 6857},
"Euler4": {Euler4(), 906609},
// "Euler5": {Euler5(), 232792560},
// "Euler6": {Euler6(), 25164150},
}
但是,如果我按照下一种方式安排评论,例如,测试就不会。
tests := map[string][]int{
//"Euler1": {Euler1(), 233168},
"Euler2": {Euler2(), 4613732},
"Euler3": {Euler3(), 6857},
"Euler4": {Euler4(), 906609},
//"Euler5": {Euler5(), 232792560},
// "Euler6": {Euler6(), 25164150},
}
测试会给我一个错误:
WARNING: DATA RACE
Write by goroutine 6:
runtime.closechan()
/private/var/folders/q8/bf_4b1ts2zj0l7b0p1dv36lr0000gp/T/workdir/go/src/runtime/chan.go:295 +0x0
github.com/alesr/project-euler.Euler2()
/Users/Alessandro/GO/src/github.com/alesr/project-euler/euler.go:40 +0xd7
github.com/alesr/project-euler.TestEulers()
/Users/Alessandro/GO/src/github.com/alesr/project-euler/euler_test.go:9 +0x46
testing.tRunner()
/private/var/folders/q8/bf_4b1ts2zj0l7b0p1dv36lr0000gp/T/workdir/go/src/testing/testing.go:456 +0xdc
Previous read by goroutine 7:
runtime.chansend()
/private/var/folders/q8/bf_4b1ts2zj0l7b0p1dv36lr0000gp/T/workdir/go/src/runtime/chan.go:107 +0x0
github.com/alesr/numbers.FibonacciGen.func1()
/Users/Alessandro/GO/src/github.com/alesr/numbers/numbers.go:103 +0x59
Goroutine 6 (running) created at:
testing.RunTests()
/private/var/folders/q8/bf_4b1ts2zj0l7b0p1dv36lr0000gp/T/workdir/go/src/testing/testing.go:561 +0xaa3
testing.(*M).Run()
/private/var/folders/q8/bf_4b1ts2zj0l7b0p1dv36lr0000gp/T/workdir/go/src/testing/testing.go:494 +0xe4
main.main()
github.com/alesr/project-euler/_test/_testmain.go:54 +0x20f
Goroutine 7 (running) created at:
github.com/alesr/numbers.FibonacciGen()
/Users/Alessandro/GO/src/github.com/alesr/numbers/numbers.go:105 +0x60
github.com/alesr/project-euler.Euler2()
/Users/Alessandro/GO/src/github.com/alesr/project-euler/euler.go:27 +0x32
github.com/alesr/project-euler.TestEulers()
/Users/Alessandro/GO/src/github.com/alesr/project-euler/euler_test.go:9 +0x46
testing.tRunner()
/private/var/folders/q8/bf_4b1ts2zj0l7b0p1dv36lr0000gp/T/workdir/go/src/testing/testing.go:456 +0xdc
==================
panic: send on closed channel
goroutine 36 [running]:
github.com/alesr/numbers.FibonacciGen.func1(0xc8200a01e0)
/Users/Alessandro/GO/src/github.com/alesr/numbers/numbers.go:103 +0x5a
created by github.com/alesr/numbers.FibonacciGen
/Users/Alessandro/GO/src/github.com/alesr/numbers/numbers.go:105 +0x61
goroutine 1 [chan receive]:
testing.RunTests(0x24d038, 0x2f7340, 0x1, 0x1, 0xf78401)
/private/var/folders/q8/bf_4b1ts2zj0l7b0p1dv36lr0000gp/T/workdir/go/src/testing/testing.go:562 +0xafa
testing.(*M).Run(0xc82004df00, 0x1ff0e8)
/private/var/folders/q8/bf_4b1ts2zj0l7b0p1dv36lr0000gp/T/workdir/go/src/testing/testing.go:494 +0xe5
main.main()
github.com/alesr/project-euler/_test/_testmain.go:54 +0x210
goroutine 17 [syscall, locked to thread]:
runtime.goexit()
/private/var/folders/q8/bf_4b1ts2zj0l7b0p1dv36lr0000gp/T/workdir/go/src/runtime/asm_amd64.s:1696 +0x1
goroutine 35 [runnable]:
github.com/alesr/strings.Flip(0xc8200727a0, 0x6, 0x0, 0x0)
/Users/Alessandro/GO/src/github.com/alesr/strings/strings.go:33 +0x17e
github.com/alesr/project-euler.Euler4(0x1ac9)
/Users/Alessandro/GO/src/github.com/alesr/project-euler/euler.go:73 +0x95
github.com/alesr/project-euler.TestEulers(0xc8200b6000)
/Users/Alessandro/GO/src/github.com/alesr/project-euler/euler_test.go:11 +0x63
testing.tRunner(0xc8200b6000, 0x2f7340)
/private/var/folders/q8/bf_4b1ts2zj0l7b0p1dv36lr0000gp/T/workdir/go/src/testing/testing.go:456 +0xdd
created by testing.RunTests
/private/var/folders/q8/bf_4b1ts2zj0l7b0p1dv36lr0000gp/T/workdir/go/src/testing/testing.go:561 +0xaa4
exit status 2
FAIL github.com/alesr/project-euler 0.022s
但是,我检查了每一个功能,它们的工作方式与预期一致。 如果需要,您可以访问Euler source code或包numbers和strings。
在Euler2函数中,我有一个延迟语句来关闭从FibonacciGen接收的通道。
在FibonacciGen上,我确实有另一个延迟声明来关闭同一个频道。
这似乎是我的第一个错误。我应该只有一个而不是两个语句来关闭频道,因为他们试图关闭同样的事情。这是对的吗?
第二个(这里我甚至更不确定),defer语句将阻止函数被调用,直到主goroutine返回,对吧?如果我在包装上打电话给我是独立的吗?
另外,由于数据正在从FibonacciGen流向主函数。对我来说,如果我关闭FibonacciGen的频道,我不需要通知主要功能。但如果我关闭主函数上的通道,我必须通知FibonacciGen停止尝试发送到此通道。
答案 0 :(得分:1)
在Euler2()
中,您不会检查频道是否已关闭。一旦关闭它就会被解锁,所以它会尝试将值发送到现在关闭的频道。
如果您只运行Euler2()
,您的程序可能会在将值发送到已关闭的频道之前退出。
答案 1 :(得分:0)
谢谢大家。在你的帮助下,我可以理解我是以错误的方式关闭了频道。
现在可以正常使用。
func Euler2() int {
c := make(chan int)
done := make(chan bool)
go numbers.FibonacciGen(c, done)
sum := 0
var f int
for {
f = <-c
if f < 4000000 {
if f%2 == 0 {
sum += f
}
} else {
close(done)
return sum
}
}
}
func FibonacciGen(c chan int, done chan bool) {
for {
select {
case <-done:
return
default:
for i, j := 0, 1; ; i, j = i+j, i {
c <- i
}
}
}
}