引用自 http://studygolang.com/articles/9701

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语言坑之for range的更多相关文章

  1. Golang 入门系列(二)学习Go语言需要注意的坑

    上一章节我们已经了解了 Go 环境的配置,不了解的,请查看前面的文章 https://www.cnblogs.com/zhangweizhong/p/9459945.html,本章节我们将学习 Go ...

  2. Go语言学习笔记十二: 范围(Range)

    Go语言学习笔记十二: 范围(Range) rang这个关键字主要用来遍历数组,切片,通道或Map.在数组和切片中返回索引值,在Map中返回key. 这个特别像python的方式.不过写法上比较怪异使 ...

  3. 狗屁不通的“视频专辑:零基础学习C语言(小甲鱼版)”(2)

    前文链接:狗屁不通的“视频专辑:零基础学习C语言(小甲鱼版)”(1) 小甲鱼在很多情况下是跟着谭浩强鹦鹉学舌,所以谭浩强书中的很多错误他又重复了一次.这样,加上他自己的错误,错谬之处难以胜数. 由于拙 ...

  4. 新学习的语言Groovy

    什么是 Groovy? Groovy 是 JVM 的一个替代语言 —替代 是指可以用 Groovy 在 Java 平台上进行 Java 编程,使用方式基本与使用 Java 代码的方式相同.在编写新应用 ...

  5. [转载]学习C语言基本思路与参考书籍

    http://zhuanlan.zhihu.com/linjr/19694823 计算机行业发展非常快,大学里的教育基本都跟不上实际的社会需求.如果你所在的学校还在指定大家使用谭浩强的教材,或使用VC ...

  6. go学习笔记-语言基础

    语言基础 结构 基础组成: 包声明 引入包 函数 变量 语句 & 表达式 注释 程序 在开始编写应用之前,我们先从最基本的程序开始,在学习大部分语言之前,都会编写一个可以输出hello wor ...

  7. (转)学习C语言基本思路与参考书籍

    计算机行业发展非常快,大学里的教育基本都跟不上实际的社会需求.如果你所在的学校还在指定大家使用谭浩强的教材,或使用VC6.0来教大家上机实验,那你不妨看看本文,这里有一些建议可以帮助你不会脱离社会太远 ...

  8. 学习go语言并完成第一个作品

    之前有使用C#写一个Windows下的发送邮件的命令行工具,方便一些脚本出现异常时向我的邮箱发送邮件提醒.但这并没有被我频繁使用,因为我的有些脚本还是在linux下面运行,因此我又有一篇文章用linu ...

  9. 笔记:学习go语言的网络基础库,并尝试搭一个简易Web框架

    在日常的 web 开发中,后端人员常基于现有的 web 框架进行开发.但单纯会用框架总感觉不太踏实,所以有空的时候还是看看这些框架是怎么实现的会比较好,万一要排查问题也快一些. 最近在学习 go 语言 ...

随机推荐

  1. tomcat+nginx+redis集群试验

    Nginx负载平衡 + Tomcat + 会话存储Redis配置要点   使用Nginx作为Tomcat的负载平衡器,Tomcat的会话Session数据存储在Redis,能够实现0当机的7x24 运 ...

  2. java分页功能代码

    import java.util.ArrayList; import java.util.List; /** * * @author cheney * * @date Aug 31, 2012 */ ...

  3. No suitable driver found for jdbc:mysql://localhost:3306/hibernate_basic

    Struts Problem Report Struts has detected an unhandled exception: Messages: No suitable driver found ...

  4. windows中修改catalina.sh上传到linux执行报错This file is needed to run this program解决

    windows中修改catalina.sh上传到linux执行报错This file is needed to run this program解决 一.发现问题 由于tomcat内存溢出,在wind ...

  5. 基于委托的C#异步编程的一个小例子 带有回调函数的例子

    我创建的是一个winform测试项目:界面如下: 设置: 下面是代码: using System; using System.Collections.Generic; using System.Com ...

  6. Android工程:引用另一个Android工程的方法详解

    本篇文章是对在Android中引用另一个Android工程的方法进行了详细的分析介绍.需要的朋友参考下   现在已经有了一个Android工程A.我们想扩展A的功能,但是不想在A的基础上做开发,于是新 ...

  7. Laravel 5 教程 - 文件上传

    一.简介 Laravel 有很棒的文件系统抽象层,是基于 Frank de Jonge 的 Flysystem 扩展包. Laravel 集成的 Flysystem 提供了简单的接口,可以操作本地端空 ...

  8. [k8s]k8s api-server启动systemd参数分析

    默认2个参数就可以启动(必需) kube-apiserver \ --service-cluster-ip-range=10.254.0.0/16 \ --etcd-servers=http://19 ...

  9. 机器学习算法( 五、Logistic回归算法)

    一.概述 这会是激动人心的一章,因为我们将首次接触到最优化算法.仔细想想就会发现,其实我们日常生活中遇到过很多最优化问题,比如如何在最短时间内从A点到达B点?如何投入最少工作量却获得最大的效益?如何设 ...

  10. Android开发基本入门,对于事件、适配器的理解不够深入

    能到处抄点代码搞出东西来了,但对事件.对ListView这类的控件,数据解析后的视图绑定,还没有完全搞清原理. 真是年纪越大,学习能力越差了.