美文网首页
Golang Range关键字的秘密

Golang Range关键字的秘密

作者: 西门吹牛々 | 来源:发表于2018-11-02 10:38 被阅读79次

    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这个遍历的地址。

    相关文章

      网友评论

          本文标题:Golang Range关键字的秘密

          本文链接:https://www.haomeiwen.com/subject/rerqxqtx.html