• 一个疑惑和三个例子

下面的程序会无限执行下去吗?

func main() {v := []int{1, 2, 3}for i := range v {v = append(v, i)}
}

答案

思考一下下面三个例子的结果。

func IndexArray() {a := [...]int{1, 2, 3, 4, 5, 6, 7, 8}for i := range a {a[3] = 100if i == 3 {fmt.Println("IndexArray", i, a[i])}}
}func IndexValueArray() {a := [...]int{1, 2, 3, 4, 5, 6, 7, 8}for i, v := range a {a[3] = 100if i == 3 {fmt.Println("IndexValueArray", i, v)}}
}func IndexValueArrayPtr() {a := [...]int{1, 2, 3, 4, 5, 6, 7, 8}for i, v := range &a {a[3] = 100if i == 3 {fmt.Println("IndexValueArrayPtr", i, v)}}
}

答案

  • range左值

可以  是 i := range 或者 i,v := range  ,变量已经被预先定义的话,这个 := 当然可以是 =  。

要注意的是 用 := 时,前面变量是被重用的,想当于第一次用的是 :=  后续循环用的是 =  。

  • range右值

可以是以下类型,或者返回以下类型的表达式

  1. array 或 array的指针
  2. slice
  3. string
  4. map
  5. 可从中接收的channel

表达式会在loop开始前计算。

如果只是i := range arr 或者 i := range *arr 这种只要数组索引的循环,由于数组是不可变的,因此在编译时候,可能直接计算len(arr),编译器直接用这个常量结果优化掉range。

  • 分析数据类型

再go中,每次分配都伴随copy,比如赋值,函数参数等。

以下几个类型的底层数据结构:

所以将一个数组分配给一个array,内存级别是整个array的一次复制。

string和slice的分配只是这两个类型头,或者叫做类型元信息结构体的复制,底层数组是没变化的。

map和channel也一样,只是指针的复制。

  • 编译器实现

range本质是for语句的一个语法糖。

编译器会在循环开始前copy一次循环对象。编译器的编译后的逻辑:

array:

slice:

可以看出数组是值类型会被整个复制一遍,大数组直接循环代价不小。应该使用数组指针来做循环对象,复制一个指针还是代价小的。

  • 关于map一个重要的信息

如果循环过程中,map的一个key-value没有被遍历到就被删除了,这个值在后续的遍历中不会出现。

遍历过程中一个key-value被创建了,继续遍历可能会遍历到这个key-value,也可能被跳过。这个应该涉及map底层的分桶实现。以后有机会介绍一下。

总之,把range理解成一个函数,被遍历的对象当作range的参数,这样理解或许更好。

以上实际是 理解半翻译 一篇博客:Go Range Loop Internals

转载于:https://www.cnblogs.com/adarking/p/8629191.html

golang range循环内部相关推荐

  1. golang for循环_10. Go语言流程控制:for 循环

    本文原文:http://golang.iswbm.com Github:http://github.com/iswbm/GolangCodingTime Go里的流程控制方法还是挺丰富,整理了下有如下 ...

  2. Golang for循环

    Golang for循环 for循环是Golang唯一的循环语句.for循环主要是用在挨个挨个取出数据的情况下.比如老师点名,老师点名的时候不可能一口气说出全班同学的名字,所以只能一个一个的点名,那么 ...

  3. stm32怎么调用for循环内部的变量_循环中的异步amp;amp;循环中的闭包

    在这之前先要了解一下 for循环中let 和var的区别 var 是函数级作用域或者全局作用域,let是块级作用域 看一个例子     function foo() {       for (var  ...

  4. 循环内部异步函数处理相关问题解析

    需求分析:根据一级标题ID筛选出所有对应的二级标题,返回一级标题ID,标题名和二级标题ID,标题名组成的数组 问题:通过forEach遍历所有一级标题取对应的ID,根据ID条件查找所有的二级标题,遍历 ...

  5. Go语言自学系列 | golang for range循环

    视频来源:B站<golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]> 一边学习一边整理老师的课程内容及试验笔记,并与大家分享,侵权即删,谢谢支持! ...

  6. golang range 遍历读写数据问题

    在Golang中使用 for range 语句进行迭代非常的便捷,但在涉及到指针时就得小心一点了. 下面的代码中定义了一个元素类型为 *int 的通道 ch : package mainimport ...

  7. Golang range解析

    目录 文章目录 目录 正文 正文 golang中的range是一个很常用的功能,可以遍历一个数组,切片等等,但是使用过程需要注意一个细节. 先举个栗子: package mainimport (&qu ...

  8. golang for循环的重新认识

    顺手写了,编译器报错 package mainimport ("fmt""time" )var ch1 = make(chan int) var ch2 = m ...

  9. golang for 循环中使用协程的问题

    两个例子 package mainimport ("fmt""time" )func Process1(tasks []string) {for _, task ...

  10. 开发这么久你真知道for循环内部执行顺序吗?

    for(System.out.print('a');num <= 3;System.out.print('c'),num++){System.out.print('b');} abcbcbc f ...

最新文章

  1. Python 常用排序Demo|冒、插、快、希等入门算法
  2. PHP学习总结(会话控制)
  3. Redis遍历方式思考--字典扩容方式
  4. python爬虫:两种方法模拟登录博客园
  5. 潍职e校帮APP功能简介
  6. python中定义变量为啥要用下划线_关于python中带下划线的变量和函数 的意义
  7. 数据集怎么导出_PCA算法 | 数据集特征数量太多怎么办?用这个算法对它降维打击...
  8. SPA是什么及原生js实现简易SPA单页面
  9. 怎么获取微信公众号的音频视频
  10. 请收下这 72 个炫酷的 CSS 技巧
  11. 绿联硬盘盒linux驱动,绿联 USB3.0 SATA 接口通用移动硬盘盒子体验与选购技巧
  12. (个人记录向)75寸电视选购
  13. intellijIdea新手上路
  14. Thinkphp5-开启调试模式
  15. vue-seamless-scroll 从入坑到放弃
  16. Ubuntu PX4无人机仿真环境配置
  17. Ubuntu16.04+cuda8.0+GTX TITAN X安装配置
  18. 首发仿拼多多源码,程序完整版+安装教程+完美运营
  19. 最简单DIY蓝牙PS2遥控器控制蓝牙智能小车
  20. PHP Apache Mysql的配置搭建及多站点配置

热门文章

  1. 7.监控应用和数据可视化 7.1通用健康状态指引器
  2. Matlab有用tips小结
  3. rand()与srand()函数用法详解
  4. 【ICLR2020】基于模型的强化学习算法玩Atari【附代码】
  5. 【浙江大学PAT真题练习乙级】1004 成绩排名 (20分) 真题解析
  6. 理解GAN生成对抗网络
  7. 矩阵分解SVD在推荐系统中的应用
  8. [洛谷P4052][JSOI2007]文本生成器
  9. BZOJ3527 推出卷积公式FFT求值
  10. scanf 与 scanf_s