You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This will generate several Its - one for each category. Note that you must assign a copy of the loop variable to a local variable (that's what category := category is doing) - otherwise the It closure will capture the mutating loop variable and all the specs will run against the last element in the loop. It is idiomatic to give the local copy the same name as the loop variable.
由此可以想到两种方案方案解决这个循环问题
for _, c := range cases {
+ c := c
Context(c.name, func() {
It("should return the expected results for "+c.name, func() {
/// checking
})
})
for _, c := range cases {
+ c := c
Context(c.name, func() {
It("should return the expected results for "+c.name, func() {
/// checking
})
})
起因
在使用 ginkgo 编写测试用例时,出现了循环只检测最后一个 test case 的情况,起初这让人十分疑惑,这并不符合认知,但确实是出现了这样的问题。
解决问题
查阅 ginkgo 的文档发现 dynamically-generating-specs 中有提到循环中出现的问题,主要是把循环变量的副本赋值给局部变量,否则无法在闭包中捕获变化的循环变量
由此可以想到两种方案方案解决这个循环问题
for _, c := range cases { + c := c Context(c.name, func() { It("should return the expected results for "+c.name, func() { /// checking }) })
for _, c := range cases { + c := c Context(c.name, func() { It("should return the expected results for "+c.name, func() { /// checking }) })
后续
网上冲浪的时候,无意间看到 Go 官方 Blog 中有一篇 Fixing For Loops in Go 1.22 的文章,这不就是我在修复 test 中遇到问题嘛,点进去好好研读一番
循环问题起初出认为是 goroutine 并发导致的混淆问题
随着时间推移还出现在不使用 goroutine 的情况下
人们才开始注意到这个问题不符合常人的认知
能力小测验:下面两个代码片段哪一个是正确修复,哪一个又是无效修复?
for _, informer := range c.informerMap { + informer := informer go informer.Run(stopCh) }
for _, a := range alarms { + a := a go a.Monitor(b) }
官方修复
Golang 1.22 及其之后的版本使用全新的语义,Golang 1.21 还可以通过
GOEXPERIMENT=loopvar
在测试或者构建中使用新循环语义GOEXPERIMENT=loopvar go test
Golang 版本低于 1.21 的版本将无法得到新语义的支持
参考
Go Blog Fixing For Loops in Go 1.22
Proposal: Less Error-Prone Loop Variable Scoping
Go Wiki: LoopvarExperiment
The text was updated successfully, but these errors were encountered: