英文:
How will iterate over a slice if that slice increases inside the loop?
问题
当我在幻灯片上迭代for循环时(下面的代码),我得到的输出是0A,1M,2C
。
代码:
x := []string{"A", "B", "C"}
for i, s := range x {
print(i, s, ",")
x[i+1] = "M"
x = append(x, "Z")
x[i+1] = "Z"
}
为什么输出结果会是这样,而不是0A, 1Z, 2Z
?
阅读文档后,我发现切片是通过指向其基础数组的指针传递给函数的。
切片在for循环中也是通过指针传递的吗?(在文档中找不到原因)
如果是这样,我猜测输出结果为0A, 1M, 2C的原因是,初始时切片是通过指针传递给循环的,当切片的容量在循环的第一次迭代中加倍时,print(i, s)的值仍然基于基础数组打印。这样理解对吗?
英文:
When I iterate through the for loop on the slide (code below), I get the output Output: 0A,1M,2C,
code:
x := []string{"A", "B", "C"}
for i, s := range x {
print(i, s, ",")
x[i+1] = "M"
x = append(x, "Z")
x[i+1] = "Z"
}
Why is the output exactly like that and not 0A, 1Z, 2Z
?
Reading the documentation, I saw that the slice is passed to the function by a pointer to the array it is based on.
Is the slice also passed to the for loop by pointer? (couldn't find why in the documentation)
If so, my guess as to why the output is exactly 0A, 1M, 2C, - because, originally, the slice was passed to the loop by pointer, and when the capacity of the slice is doubled in the first iteration of the loop, the print(i, s) values are still printed based on the base array. Is this true?
答案1
得分: 1
append
可以分配一个新的数组。在第一个append
之后,x
现在是一个副本,你正在循环遍历原始数组。对x
的更改现在不会影响s
。
让我们在循环中添加一些调试信息来查看。
x := []string{"A", "B", "C"}
for i, s := range x {
fmt.Printf("Start: i=%v s=%v x=%p %v\n", i, s, x, x)
x[i+1] = "M"
fmt.Printf("After x[i+1] = \"M\": i=%v s=%v x=%p %v\n", i, s, x, x)
x = append(x, "Z")
fmt.Printf("After Append: i=%v s=%v x=%p %v\n", i, s, x, x)
x[i+1] = "Z"
fmt.Printf("After x[i+1] = \"Z\": i=%v s=%v x=%p %v\n\n", i, s, x, x)
}
结果如下:
Start: i=0 s=A x=0xc0000161b0 [A B C]
After x[i+1] = "M": i=0 s=A x=0xc0000161b0 [A M C]
After Append: i=0 s=A x=0xc000062180 [A M C Z]
After x[i+1] = "Z": i=0 s=A x=0xc000062180 [A Z C Z]
Start: i=1 s=M x=0xc000062180 [A Z C Z]
After x[i+1] = "M": i=1 s=M x=0xc000062180 [A Z M Z]
After Append: i=1 s=M x=0xc000062180 [A Z M Z Z]
After x[i+1] = "Z": i=1 s=M x=0xc000062180 [A Z Z Z Z]
Start: i=2 s=C x=0xc000062180 [A Z Z Z Z]
After x[i+1] = "M": i=2 s=C x=0xc000062180 [A Z Z M Z]
After Append: i=2 s=C x=0xc000062180 [A Z Z M Z Z]
After x[i+1] = "Z": i=2 s=C x=0xc000062180 [A Z Z Z Z Z]
注意,在第一个append
之后,x
的地址发生了变化。任何x[i+1] = ?
的更改都不再影响s
。
英文:
append
can allocate a new array. It does. After the first append
, x
is now a copy and you're looping over the original. Changes to x
now have no affect on s
.
Let's mark up the loop with some more debugging to see.
x := []string{"A", "B", "C"}
for i, s := range x {
fmt.Printf("Start: i=%v s=%v x=%p %v\n", i, s, x, x)
x[i+1] = "M"
fmt.Printf("After x[i+1] = \"M\": i=%v s=%v x=%p %v\n", i, s, x, x)
x = append(x, "Z")
fmt.Printf("After Append: i=%v s=%v x=%p %v\n", i, s, x, x)
x[i+1] = "Z"
fmt.Printf("After x[i+1] = \"Z\": i=%v s=%v x=%p %v\n\n", i, s, x, x)
}
Start: i=0 s=A x=0xc0000161b0 [A B C]
After x[i+1] = "M": i=0 s=A x=0xc0000161b0 [A M C]
After Append: i=0 s=A x=0xc000062180 [A M C Z]
After x[i+1] = "Z": i=0 s=A x=0xc000062180 [A Z C Z]
Start: i=1 s=M x=0xc000062180 [A Z C Z]
After x[i+1] = "M": i=1 s=M x=0xc000062180 [A Z M Z]
After Append: i=1 s=M x=0xc000062180 [A Z M Z Z]
After x[i+1] = "Z": i=1 s=M x=0xc000062180 [A Z Z Z Z]
Start: i=2 s=C x=0xc000062180 [A Z Z Z Z]
After x[i+1] = "M": i=2 s=C x=0xc000062180 [A Z Z M Z]
After Append: i=2 s=C x=0xc000062180 [A Z Z M Z Z]
After x[i+1] = "Z": i=2 s=C x=0xc000062180 [A Z Z Z Z Z]
Note how after the first append
the address of x
changes. Any x[i+
] = ?no longer affect
s`.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论