Scopelint 錯誤:在範圍範圍上使用變數
在測試函數TestGetUID 中,程式碼遇到了由scopelint報告的錯誤,該錯誤會發出警告在函數文字中使用range 範圍內的變數x。
考慮以下程式碼行:
<code class="go">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) }) }</code>
錯誤與這些行有關,因為 x 是 range 循環迭代中的循環變數在測試切片上。 Scopelint 偵測到 x 正在傳遞給 t.Run() 的函數文字中使用,如果在 t.Run() 返回後呼叫函數文字,則可能會導致潛在問題。
原因和最佳實踐
出現此問題的原因是編譯器無法保證創建並傳遞給t.Run() 的函數文字在t.Run( ) 退出後不會被呼叫。如果在 t.Run() 返回後呼叫函數文字,它們將引用 x 變量,該變數可能已被循環後續迭代中的值覆蓋。
Go vet 會將此警告提出防止這種意外行為,如果函數文字在不同的 goroutine 中同時執行,可能會導致錯誤甚至資料競爭。
在這種情況下建議的最佳實踐是傳遞值將循環變數作為參數傳遞給函數文字,或者創建循環變數的副本並引用函數文字中的副本。由於函數字面量的簽章無法更改,建議的解決方案是建立副本,例如:
<code class="go">x2 := x</code>
聲明此副本後,函數字面量中的x 識別碼將引用本機副本,而不是循環變數。雖然為副本分配相同的名稱可能看起來很混亂,但它清楚地表明了使用副本的意圖。
以上是## Scopelint 錯誤:在範圍範圍內使用變數 - 如何安全地引用函數文字中的循環變數?的詳細內容。更多資訊請關注PHP中文網其他相關文章!