【GoLand】for循环range原理

810 阅读1分钟

一、range易错用法

1.错误用法

如下代码与预期不符,预期应该是map的value依次是1,2,3,4

package main

import "fmt"

func main() {
    slice := []int{0, 1, 2, 3}
    myMap := make(map[int]*int)

    for index, value := range slice {
        myMap[index] = &value
    }
    fmt.Println("=====new map=====")
    prtMap(myMap)
}

func prtMap(myMap map[int]*int) {
    for key, value := range myMap {
        fmt.Printf("map[%v]=%v\n", key, *value)
    }
}

2.正确用法

如下代码运行符合预期结果

package main

import "fmt"

func main() {
    slice := []int{0, 1, 2, 3}
    myMap := make(map[int]*int)

    for index, value := range slice {
        fmt.Println("value:", &value, value)
        num := value
        fmt.Println("num:", &num, num)
        myMap[index] = &num
    }
    fmt.Println("=====new map=====")
    prtMap(myMap)
}

func prtMap(myMap map[int]*int) {
    for key, value := range myMap {
        fmt.Printf("map[%v]=%v\n", key, *value)
    }
}

二、range原理

观察代码结果,发现value的地址都一样,num的地址不一样,value每次赋值会被改变,range的真实设计模式可以类比如下代码逻辑,value 实际是一个for循环外部的一个内存地址,每次循环的值会写入value所在内存中,但是如果直接使用这块地址,就会导致所有的map元素指向同一块地址,最后所有的map元素的值都是最后一次循环给value中写入的值

var value int
for index, v := range slice {
    value = v
    myMap[index] = &value
}