一、用法
range 类似迭代器,可以遍历数组,字符串,map 等等,对象的不同,返回的结果也不同。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package main import "fmt" func main(){ //数组的遍历 a := [3]int {1, 2, 3} for i, n := range a{ fmt.Println(i, n) } //切片的遍历 b := []int{2, 3, 4} for i, n := range b{ fmt.Println(i, n) } //map 的遍历 c := map[string]int{"Hello":1, "World":2} for k, v := range c{ fmt.Println(k, v) } } |
结果:
1 2 3 4 5 6 7 8 9 10 |
0 1 1 2 2 3 0 2 1 3 2 4 Hello 1 World 2 |
二、注意事项
1. range 会复制对象,而不是不是直接在原对象上操作。
示例一:
1 2 3 4 5 6 7 8 9 10 11 12 |
package main import "fmt" func main(){ a := [3]int {1, 2, 3} for _, v := range a{ //复制一份 a 遍历 [1, 2, 3] v += 100 //v 是复制对象中的值,不会改变 a 数组元素的值 } fmt.Println(a) //1 2 3 } |
示例二:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package main import "fmt" func main(){ a := [3]int {1, 2, 3} for i, v := range a{ //i,v 从 a 复制的对象里提取出 if i == 0{ a[1], a[2] = 200, 300 fmt.Println(a) //输出 [1 200 300] } a[i] = v + 100 //v 是复制对象里的元素 [1, 2, 3] } fmt.Println(a) //输出 [101, 102, 103] } |
2. 使用 range 迭代遍历引用类型时,底层的数据不会被复制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package main import "fmt" func main(){ a := []int {1, 2, 3} //改成 slice for i, v := range a{ if i == 0{ a[1], a[2] = 200, 300 fmt.Println(a) //[1 200 300] } a[i] = v + 100 } fmt.Println(a) } |
结果:
1 2 |
[1 200 300] [101 300 400] |
因为切片的内部结构为 struct slice{*point, len, cap} 。
数据部分是一个指针,指向地址,复制对象的时候只是把指针的值复制了,而不是重新拷贝一块新的内存再把值放进去,所以修改的时候还是修改的原来的值,和 C++里的浅拷贝一样。
评论