golang for-range迭代问题浅析

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

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迭代问题浅析)