想想下面代码会发生什么?
func main() {
a := []int{1, 2, 3}
for _, v := range a {
a = append(a, v)
fmt.Println("len(a)=", len(a))
}
fmt.Printf("a is %#v", a)
}
会造成死循环吗? 答案是:不会。
对于 Go
中的 for ... range
而言,实际上在循环之前就已经获取了切片的长度,然后再执行固定次数的循环,所以上面代码打印结果是:
len(a)= 4
len(a)= 5
len(a)= 6
a is []int{1, 2, 3, 1, 2, 3}
对于切片的 for range
,它的底层代码是:
for_temp := range
len_temp := len(for_temp)
for index_temp = 0; index_temp < len_temp; index_temp++ {
value_temp = for_temp[index_temp]
index = index_temp
value = value_temp
original body
}
可以看到,在遍历之前就已经获取的切片的长度 len_temp := len(for_temp)
,所以遍历的次数不会随着切片的变化而变化,上面的代码自然不会是死循环了。
上面代码会被 Go
当做以下代码执行:
func main() {
a := []int{1, 2, 3}
for_temp := a
len_temp := len(for_temp)
for index_temp := 0; index_temp < len_temp; index_temp++ {
value_temp := for_temp[index_temp]
_ = index_temp
value := value_temp
a = append(a, value)
fmt.Println("len(a)=", len(a))
}
fmt.Printf("a is %#v", a)
}
参考: