Scopelint 错误:在范围范围上使用变量
在测试函数 TestGetUID 中,代码遇到了scopelint 报告的错误,该错误会发出警告使用函数字面量范围内的变量 x。
考虑以下代码行:
for _, x := range tests {
t.Run(x.description, func(t *testing.T) {
client := fake.NewSimpleClientset(x.objs...)
actual := getUID(client, x.namespace)
assert.Equal(t, x.expected, actual)
})
}
错误与这些行有关,因为 x 是在测试切片上迭代的范围循环内的循环变量。 Scopelint 检测到 x 正在传递给 t.Run() 的函数文字中使用,如果在 t.Run() 返回后调用函数文字,则可能会导致潜在问题。
原因和最佳实践
出现这个问题是因为编译器无法保证创建并传递给 t.Run() 的函数文字在之后不会被调用t.Run() 退出。如果在 t.Run() 返回后调用函数文字,它们将引用 x 变量,该变量可能已被循环后续迭代中的值覆盖。
Go vet 会将此警告提出防止这种意外行为,如果函数文字在不同的 goroutine 中同时执行,可能会导致错误甚至数据竞争。
在这种情况下,建议的最佳实践是通过循环变量的值作为参数传递给函数文字,或者创建循环变量的副本并引用函数文字内的副本。由于函数字面量的签名无法更改,建议的解决方案是创建一个副本,例如:
x2 := x
声明此副本后,函数文字将引用本地副本,而不是循环变量。虽然为副本分配相同的名称可能看起来很混乱,但它清楚地表明了使用副本的意图。
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3