Go 语言中 range 关键字用于 for 循环中迭代,支持类型如下:
- 数组(array)
- 切片(slice)
- 通道(channel)
- 集合(map)
它返回元素的索引和索引对应的值,在集合中返回 key-value 对的 key 值。
使用起来非常方便
for index, value := range myArray {
fmt.Println("index: " + index)
fmt.Println("value: " + value)
}
这个简单的使用方法里面,对新手来说,还是有坑的,而且非常不容易被发现。
package main
import "fmt"
type student struct {
Name string
Age int
}
func main() {
var stus []student
stus = []student{
{Name: "one", Age: 18},
{Name: "two", Age: 19},
}
data := make(map[int]*student)
// code1 这是不对的使用方法
for i, v := range stus {
data[i] = &v
}
for i, v := range data {
fmt.Printf("error: key=%d, value=%v \n", i, *v)
}
// code2 这是正确的使用方法
for i, _ := range stus {
data[i] = &stus[i]
}
for i, v := range data {
fmt.Printf("right: key=%d, value=%v \n", i, *v)
}
}
输出结果是:
error: key=0, value={two 19}
error: key=1, value={two 19}
right: key=0, value={one 18}
right: key=1, value={two 19}
原因很明显:
用for range来遍历的时候,被遍历的指针是不变的,每次遍历仅执行struct值的拷贝,即上面代码中的变遍历的 [v] 是对struct的值拷贝,因此 code1中 data[i] = &v 永远取的值都是 v这个遍历的地址。