英文:
panic: testing: Verbose called before Init
问题
尝试运行 https://github.com/adonovan/gopl.io/blob/master/ch8/cake/cake_test.go,但是出现了以下错误:
panic: testing: Verbose called before Init
goroutine 1 [running]:
testing.Verbose(...)
/usr/lib/go-1.17/src/testing/testing.go:453
.../cake_test.init()
错误显示来自 cake_test.init()
,但是 cake_test.go
文件中并没有包含 init()
函数:
$ grep init cake_test.go | wc
0 0 0
请问问题出在哪里?
英文:
Trying to run
https://github.com/adonovan/gopl.io/blob/master/ch8/cake/cake_test.go
but got
panic: testing: Verbose called before Init
goroutine 1 [running]:
testing.Verbose(...)
/usr/lib/go-1.17/src/testing/testing.go:453
.../cake_test.init()
It says the error comes from cake_test.init()
, yet the cake_test.go
file doesn't contain init()
:
$ grep init cake_test.go | wc
0 0 0
What exactly is the problem?
答案1
得分: 2
这是因为测试包本身有一个init函数来处理测试标志,并且你调用了Verbose来创建一个全局变量。
为了避免这个问题,你可以尝试以下方法:
- 使用函数指针来捕获testing.Verbose,并在所有初始化之后的函数中使用它(Verbose的类型将是
func() bool
),但我认为这种方法比较复杂。 - 添加一个辅助函数,在每个测试中创建一个新的默认值,并安全地调用testing.Verbose。
- 创建一个构造函数(而不是测试辅助函数),用最常见的选项填充,并在每个测试中设置Verbose的值。
- 创建两个构造函数,第二个构造函数接收Verbose的值作为参数。
另外,考虑创建一个名为Debug
的方法,与Println具有相同的签名,如果Verbose为true,则调用fmt.Println。
如果你有一个构造函数,你可以创建一个第二个字段:Logger,它是一个与Println具有相同签名的函数指针,并将其初始化为fmt.Println,在测试中你可以将其设置为t.Log,以获得更好的体验。
当然,也许有些建议比其他建议更高级,你可以自由尝试并选择最好的方法。
英文:
This happens because the testing package itself has a init to process test flags and you are callind Verbose to create a global variable
https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/testing/testing.go;l=548
To avoid this you can:
- Use a ponter to function to capture testing.Verbose and use inside functions, after all initializations ( Verbose will be type
func() bool
) but I think this is complex - Add a helper that creates a new default on each test with a safe call to testing.Verbose
- Create a constructor (instead a test helper) that fill with the most common options and you can set the value of Verbose on each test
- Create a two constructors, a second one that receive the value of Verbose
Also, Consider create a method Debug
with same signature of Println, to call fmt.Println if Verbose is true
If you have a constructor, you can create a second field: Logger, with is a ponter to function with same signature as Println and you initialize with fmt.Println and in the tests you can set as t.Log to have a better experience
Of course perhaps some suggestions are more advanced than others, feel free to play a little bit and choose the best ones
答案2
得分: 2
对于这个特定的情况,添加Init()函数就解决了问题。
var defaults cake.Shop
func Init() {
defaults = cake.Shop{
Verbose: testing.Verbose(),
Cakes: 20,
BakeTime: 10 * time.Millisecond,
NumIcers: 1,
IceTime: 10 * time.Millisecond,
InscribeTime: 10 * time.Millisecond,
}
}
英文:
For this specific case, adding Init() function did the trick.
var defaults cake.Shop
func Init() {
defaults = cake.Shop{
Verbose: testing.Verbose(),
Cakes: 20,
BakeTime: 10 * time.Millisecond,
NumIcers: 1,
IceTime: 10 * time.Millisecond,
InscribeTime: 10 * time.Millisecond,
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论