for range能完成數據的迭代,支持字符串、數組、數組指針、切片、字典、通道類型,返回索引、鍵值數據。再次我們只討論在數組和切片中的使用。
1.在數組中迭代數據
main(){
numbers:=[6]int{1,2,3,4,5,6}
for i,v:= range numbers{
fmt.Printf("%X %X %v %v\n",&i,&v,i,v)
v++
}
fmt.Println(numbers)
}
輸出
C00000A0C0 C00000A0C8 0 1
C00000A0C0 C00000A0C8 1 2
C00000A0C0 C00000A0C8 2 3
C00000A0C0 C00000A0C8 3 4
C00000A0C0 C00000A0C8 4 5
C00000A0C0 C00000A0C8 5 6
[1 2 3 4 5 6]
細心的同學可能發現了,索引和值的地址都沒有變化,定義的局部變量會被重複使用。而且局部變量的改變,並不會修改原變量的值。儘管v自增了,但是原數組還是沒變。
2.range會複製目標數據
main(){
data1:=[5]int{1,2,3,4,5}
for i,v:= range data1{ //i,v會從data1複製品中取值
if i==0 {
data1[0] += 100
data1[1] += 200
data1[2] += 300
}
fmt.Printf("v:%d,data1:%d\n",v,data1[i])
}
fmt.Println("----------------")
data2:=[]int{1,2,3,4,5}
for i,v:= range data1{ //僅複製slice,不包括底層數組,i,v會從複製出來的切片中取值
if i==0 {
data2[0] += 100
data2[1] += 200
data2[2] += 300
}
fmt.Printf("v:%d,data2:%d\n",v,data2[i])
}
}
以上會輸出
v:1,data1:101
v:2,data1:202
v:3,data1:303
v:4,data1:4
v:5,data1:5
----------------
v:101,data2:101
v:202,data2:202
v:303,data2:303
v:4,data2:4
v:5,data2:5
在range開始迭代時,會拷貝一個副本,對數組來說,修改原數組不會修改被迭代的數組,而對切片來說,range拷貝的切片和原切片都指向同一底層數組,所以修改了原切片也會影響迭代的切片。
3.如果range目標表達式是函數調用,也僅被執行一次
main(){
for i,v:=range data(){
fmt.Println(i,v)
}
}
func data()[]int {
fmt.Println("origin data")
return []int{1,2,3}
}
輸出
origin data
0 1
1 2
2 3