美文网首页
golang for-range迭代问题浅析

golang for-range迭代问题浅析

作者: 时彬斌 | 来源:发表于2020-08-11 16:27 被阅读0次

日常开发中尝尝需要对数组进行迭代,遍历所有的值并对远有的数组进行新的赋值操作,举个例子:

firstStrs := []string{"aa", "bb", "cc", "dd"}
    for _, v :=range firstStrs {
        var secondStrs []string
        if v == "aa" {
            secondStrs = append(secondStrs, v)
        }
        firstStrs = secondStrs
    }

问题: for-range会迭代几次,最后firstStrs的值又是多少呢,还有一个有趣的问题是如果把if v== aa 去掉,这个循环会结束吗(不停地向数组里append);
在开始回答这个问题之前我们先了解下for-range的语法:
如上面代码所示: :=range 即可对slice 、array、string、map 、channel进行遍历迭代:
下面看下对于array的迭代实现,参看:https://github.com/golang/gofrontend/blob/e387439bfd24d5e142874b8e68e7039f74c744d7/go/statements.cc#L5384

// Lower a for range over an array.

void
For_range_statement::lower_range_array(Gogo* gogo,
                       Block* enclosing,
                       Block* body_block,
                       Named_object* range_object,
                       Temporary_statement* range_temp,
                       Temporary_statement* index_temp,
                       Temporary_statement* value_temp,
                       Block** pinit,
                       Expression** pcond,
                       Block** piter_init,
                       Block** ppost)
{
  Location loc = this->location();

  // The loop we generate:
  //   len_temp := len(range)
  //   range_temp := range
  //   for index_temp = 0; index_temp < len_temp; index_temp++ {
  //           value_temp = range_temp[index_temp]
  //           index = index_temp
  //           value = value_temp
  //           original body
  //   }

  // Set *PINIT to
  //   var len_temp int
  //   len_temp = len(range)
  //   index_temp = 0

实际可以看到内部实际上使用了一个局部变量,在开始迭代时赋值,所以在迭代过程中重新赋值对于当前的range操作也是没有影响的;
另外注意value信息的取值,定义了一个变量value_temp,即每次都会对value进行重新赋值,但是指针或者叫地址确是没有改变,所以在迭代中我们如果是通过指针去获取当前的value信息时,只会取到最后一次迭代的赋值的信息:
可以通过如下代码查看:

firstStrs := []string{"aa", "bb", "cc", "dd"}
    for _, v :=range firstStrs {
        //var secondStrs []string
        fmt.Println(v)
        fmt.Println(&v)
    }

--------

aa
0xc000090120
bb
0xc000090120
cc
0xc000090120
dd
0xc000090120

可以看到地址是同一个;
总结:for range 时实际循环的值只是被range值拷贝出来的副本。

相关文章

  • golang for-range迭代问题浅析

    日常开发中尝尝需要对数组进行迭代,遍历所有的值并对远有的数组进行新的赋值操作,举个例子: 问题: for-rang...

  • Go语言学习笔记(3)

    数组 Golang 中,数组是值类型。 数组的声明 数组的初始化 用 for-range 遍历数组 基本语法: 其...

  • C++ Primer: String, Vector and A

    1. String 处理字符串 cctype 处理每个字符 for-range 语句 for-range 改变字符...

  • 浅析 go sync包

    浅析 go sync包 背景介绍 尽管 Golang 推荐通过 channel 进行通信和同步,但在实际开发中 s...

  • golang 指针浅析

    指针这个东西,不管是在哪个语言里,都算是比较难懂的概念,其实只要解释清楚,指针的概念并不难理解。 golang中打...

  • Golang error浅析

    由于Golang的语言设计的原因,不管是不是愿意,每个golang开发者的几乎每一段代码都需要与error做缠斗。...

  • 浅析 golang module

    什么是 module?module 解决了什么问题? module 代表一个版本管理单元,它包括一个或者多个 pa...

  • 微信版本迭代上

    微信版本迭代 微信改变了我们的生活方式文章从微信的版本迭代,浅析产品功能需求背后用户的心理。

  • 浅析python迭代器

    可迭代对象Iterable 可迭代对象是什么?简单点说,那些能被for循环的对象就是可迭代对象。精确一点来说可迭代...

  • 浅析梯度迭代算法

    梯度迭代类算法已成为目前各种领域的主流算法。各种现实中的问题分解抽象成机器可以处理的形式之后,基本都可归类为图像、...

网友评论

      本文标题:golang for-range迭代问题浅析

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