引用自 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. Thread.sleep(0)的作用

    我们可能经常会用到 Thread.Sleep 函数来使线程挂起一段时间.那么你有没有正确的理解这个函数的用法呢?思考下面这两个问题: 假设现在是 2008-4-7 12:00:00.000,如果我调用 ...

  2. 插入排序(PHP,C)

    PHP<?php /* ** 功能:插入算法 ** 描述: ** 作者:yuwensong */ function insertSorting($arr,$n){ for($i = 1; $i& ...

  3. adb 修改手机代理方式

    一.使用全局命令 设置代理: adb shell settings put global http_proxy 代理IP地址:端口号 如: adb shell settings put global ...

  4. https://github.com/CocoaPods/CocoaPods/search?q=No+such+file+or+directory报错解决方式

    ――― MARKDOWN TEMPLATE ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― ### Command ``` /U ...

  5. 【iOS开发-33】学习手动内存管理临时抛弃ARC以及retain/assign知识——iOSproject师面试必考内容

    我们为什么须要内存管理?当使用内存达到40M和45M时候会发出警告,假设不处理,占用内存达到120M时直接强制关闭程序. 所以出现闪退除了是程序出现逻辑错误,还有可能是内存使用过大. (1)创建一个对 ...

  6. rownum使用说明

    参考:http://www.blogjava.net/conans/articles/219693.html 参考:http://www.blogjava.net/freeman1984/archiv ...

  7. php 获取客户端的浏览器信息

     就是访问的时候,通过服务端来判断用户是否为移动端,如果是的话就重定向(移动端的页面).事实上现在都是一套搞定的了. 但是还是记录一下吧.没准以后用的到   http://detectmobilebr ...

  8. 在centos 5.11上安装pylint

    上午花了两三个小时在折腾pylint的安装. 如果是普通的linux倒也简单,只用运行一个pip install pylint就行了. 可是偏偏那么巧,服务器的版本是centos 5.11 这个版本对 ...

  9. maven添加额外archetype

    用Eclipse + m2e 插件新建maven项目时发现archetype太少了,网上搜索如何添加额外的archetype. http://maven.apache.org/archetype/ma ...

  10. Android实现微信自己主动抢红包的程序

    简单实现了微信自己主动抢红包的服务,原理就是依据keyword找到对应的View, 然后自己主动点击.主要是用到AccessibilityService这个辅助服务,基本能够满足自己主动抢红包的功能, ...