Golang 語言 For 和 For-range 的區別
1介紹
在 Golang 語言中,僅有 for 一種循環語句,但是可以模擬 while (condition) {} 和 while (true) {}。
除此之外,Golang 語言還引入了另外一個關鍵字 range,我們也可以配合 for 關鍵字,使用 for-range循環遍歷數據。
本文我們介紹一下使用 for 和 for-range 循環遍歷數據的區別。
2區別
在 Golang 語言程序開發中,經常會使用循環遍歷數據,因為 Golang 語言提供了 for-range 范圍遍歷,可以更加方便的幫助我們循環遍歷數據,比如數據和數組指針、切片、字符串、映射和通道,所以我們比較喜歡使用 for-range 范圍遍歷替代 for 普通遍歷。
實際上,使用范圍遍歷 for-range 和使用普通遍歷 for 是有區別的,因為范圍遍歷會在遍歷之前,先拷貝一份被遍歷的數據,然后遍歷拷貝的數據。
3踩「坑」
在 Golang 語言程序開發中,因為不了解使用范圍遍歷切片和使用普通遍歷切片的區別,新手經常會在此踩“坑”。
范圍遍歷切片
- func main() {
- s := []int{0, 1}
- for _, v := range s {
- s = append(s, v)
- }
- fmt.Printf("s=%v\n", s)
- }
輸出結果:
- s=[0 1 0 1]
普通遍歷切片
- func main() {
- s := []int{0, 1}
- for i := 0; i < len(s); i++ {
- s = append(s, s[i])
- }
- fmt.Printf("s=%v\n", s)
- }
輸出結果:
閱讀上面這段代碼,我們分別使用范圍遍歷和普通遍歷,循環遍歷同一個切片。范圍遍歷可以輸出結果,而普通遍歷是無限循環,無法輸出結果。
原因是范圍遍歷在開始遍歷數據之前,會先拷貝一份被遍歷的數據,所以在遍歷過程中去修改被遍歷的數據,只是修改拷貝的數據,不會影響到原數據。
在該示例代碼中,我們在循環過程中,不斷追加數據到切片,原以為范圍遍歷也可以像普通遍歷那樣,無限循環,但是實際上結果并非所想。
同時,因為范圍遍歷會拷貝被遍歷數據,所以在需要遍歷內存占用比較大的數組時,建議使用普通遍歷,如果必須使用范圍遍歷,我們可以遍歷數組的地址或先將數組轉換為切片,然后再遍歷。
4總結
本文我們介紹了在 Golang 語言中,循環遍歷數據的兩種方式之間有什么區別,其中最大的區別,也是最容易踩“坑”的地方,就是范圍遍歷會在遍歷之前,先拷貝一份被遍歷的數據,然后遍歷拷貝的數據。
如果讀者朋友們不清楚這個區別,在程序開發中,肯定會遇到這樣或那樣的“坑”,而且還很難發現和繞過。
除了文中列舉的示例,相信讀者朋友們肯定還有很多其他踩“坑”場景,歡迎在留言區與大家分享。
參考資料:
https://gobyexample.com/range
https://go.dev/tour/moretypes/16
https://go.dev/ref/spec#For_statements
https://www.geeksforgeeks.org/range-keyword-in-golang/
https://golangbyexample.com/understand-for-range-loop-golang/
https://www.educative.io/edpresso/what-is-the-for-range-loop-in-golang