美文网首页GolangGolang程序员
go语言坑之for range

go语言坑之for range

作者: songleo | 来源:发表于2017-04-04 11:27 被阅读325次

go只提供了一种循环方式,即for循环,在使用时可以像c那样使用,也可以通过for range方式遍历容器类型如数组、切片和映射。但是在使用for range时,如果使用不当,就会出现一些问题,导致程序运行行为不如预期。比如,下面的示例程序将遍历一个切片,并将切片的值当成映射的键和值存入,切片类型是一个int型,映射的类型是键为int型,值为*int,即值是一个地址。

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)
    }
}

运行程序输出如下:

=====new map=====
map[3]=3
map[0]=3
map[1]=3
map[2]=3

由输出可以知道,不是我们预期的输出,正确输出应该如下:

=====new map=====
map[0]=0
map[1]=1
map[2]=2
map[3]=3

但是由输出可以知道,映射的值都相同且都是3。其实可以猜测映射的值都是同一个地址,遍历到切片的最后一个元素3时,将3写入了该地址,所以导致映射所有值都相同。其实真实原因也是如此,因为for range创建了每个元素的副本,而不是直接返回每个元素的引用,如果使用该值变量的地址作为指向每个元素的指针,就会导致错误,在迭代时,返回的变量是一个迭代过程中根据切片依次赋值的新变量,所以值的地址总是相同的,导致结果不如预期。

修正后程序如下:

package main

import "fmt"

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

    for index, value := range slice {
        num := value
        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)
    }
}

运行程序输出如下:

=====new map=====
map[2]=2
map[3]=3
map[0]=0
map[1]=1
本次荐书:算法图解
算法图解算法图解

相关文章

  • Go 学习

    go语言局部变量分配在栈还是堆Golang 垃圾回收剖析go语言坑之for range

  • go语言坑之for range

    go只提供了一种循环方式,即for循环,在使用时可以像c那样使用,也可以通过for range方式遍历容器类型如数...

  • Go 语言中的 go range 循环

    看了好多文章都发现了 go 语言中的 defer 和 go range 循环的坑点,但是很多文章都没有发现这一坑点...

  • 八、Go range的用法

    八、Go语言range Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slic...

  • range迭代中的坑

    go语言中range的坑,代码如下 坑2: 为什么输出结果如此没规律: 希望有知道的朋友解答下!谢谢~~

  • Go语言中for range的"坑"

    前言 Go 中的for range组合可以和方便的实现对一个数组或切片进行遍历,但是在某些情况下使用for ran...

  • Learn Golang in Days - Day 11

    Learn Golang in Days - Day 11 要点 Range Go语言中range关键字用于for...

  • Go语言For Range小记

    由于Go的SDK及IDE的升级,语法、方法都会有变化,就会出现黄色警告。 为了防止按提示更新后线上出现重大BUG,...

  • Go语言范围(Range)

    Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channe...

  • golang内存逃逸

    一篇很好的博客: Go 语言机制之栈与指针 Go 语言机制之逃逸分析 Go 语言机制之内存剖析 Go 语言机制之数...

网友评论

    本文标题: go语言坑之for range

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