詳解Go語言中for range的"坑"
前言
Go 中的for range組合可以和方便的實現(xiàn)對一個數(shù)組或切片進(jìn)行遍歷,但是在某些情況下使用for range時很可能就會被"坑",下面用一段代碼來模擬下:
func main() { arr1 := []int{1, 2, 3} arr2 := make([]*int, len(arr1)) for i, v := range arr1 { arr2[i] = &v } for _, v := range arr2 { fmt.Println(*v) } }
代碼解析:
- 創(chuàng)建一個int slice,變量名為arr1并初始化 1,2,3 作為切片的值。
- 創(chuàng)建一個*int slice,變量名為arr2。
- 通過for range遍歷arr1,然后獲取每一個元素的指針,賦值到對應(yīng)arr2中。
- 逐行打印arr2中每個元素的值。
從代碼上看,打印出來的結(jié)果應(yīng)該是
1
2
3
然而真正的結(jié)果是
3
3
3
原因
因為for range在遍歷值類型時,其中的v變量是一個值的拷貝,當(dāng)使用&獲取指針時,實際上是獲取到v這個臨時變量的指針,而v變量在for range中只會創(chuàng)建一次,之后循環(huán)中會被一直重復(fù)使用,所以在arr2賦值的時候其實都是v變量的指針,而&v最終會指向arr1最后一個元素的值拷貝。
來看看下面這個代碼,用for i來模擬for range,這樣更易于理解:
func main() { arr1 := []int{1, 2, 3} arr2 := make([]*int, len(arr1)) var v int for i:=0;i<len(arr1);i++ { v = arr1[i] arr2[i] = &v } for _, v := range arr2 { fmt.Println(*v) } }
解決方案
傳遞原始指針
func main() { arr1 := []int{1, 2, 3} arr2 := make([]*int, len(arr1)) for i := range arr1 { arr2[i] = &arr1[i] } for _, v := range arr2 { fmt.Println(*v) } }
使用臨時變量
func main() { arr1 := []int{1, 2, 3} arr2 := make([]*int, len(arr1)) for i, v := range arr1 { t := v arr2[i] = &t } for _, v := range arr2 { fmt.Println(*v) } }
使用閉包
func main() { arr1 := []int{1, 2, 3} arr2 := make([]*int, len(arr1)) for i, v := range arr1 { func(v int){ arr2[i] = &v }(v) } for _, v := range arr2 { fmt.Println(*v) } }
官方提示
由于這一問題過于普遍,Golang甚至將其寫入了文檔的『常見錯誤』部分:文檔
到此這篇關(guān)于詳解Go語言中for range的"坑"的文章就介紹到這了,更多相關(guān)Go語言for range內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go?interface?接口的最佳實踐經(jīng)驗分享
go?的接口在go的編程里面用的十分頻繁,尤其是空接口的使用,因為有了接口,才使得Go語言變得異常的強大,今天給大家介紹下Go?interface?接口的最佳實踐經(jīng)驗分享,感興趣的朋友一起看看吧2022-04-04Go+Redis緩存設(shè)計與優(yōu)化實現(xiàn)
本文主要介紹了Go+Redis緩存設(shè)計與優(yōu)化實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-02-02Go項目與Docker結(jié)合實現(xiàn)高效部署深入探究
在現(xiàn)代軟件開發(fā)中,使用Docker部署應(yīng)用程序已經(jīng)成為一種標(biāo)準(zhǔn)實踐,本文將深入探討如何將Go項目與Docker結(jié)合,實現(xiàn)高效、可靠的部署過程,通過詳細(xì)的步驟和豐富的示例,你將能夠迅速掌握這一流程2023-12-12Ruby序列化和持久化存儲(Marshal、Pstore)操作方法詳解
這篇文章主要介紹了Ruby序列化和持久化存儲(Marshal、Pstore)操作方法詳解,包括Ruby Marshal序列化,Ruby Pstore存儲,需要的朋友可以參考下2022-04-04