日常开发中尝尝需要对数组进行迭代,遍历所有的值并对远有的数组进行新的赋值操作,举个例子:
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值拷贝出来的副本。
网友评论