红颜莎娜
在内部,切片就像一个包含三个元素的结构:一个支持数组后备数组的大小,可以访问为 cap(slice)切片的长度,可以访问为 len(slice)在您的循环运行之前,支持数组 fora是[0, 1, 2, 3]with cap(a) == len(a) == 4。当您a使用以下代码进行修改时:a = append(a[:i], a[i+1:]...)a由于新长度小于容量,因此新值共享原始的后备数组。因此,在第一次迭代中修改后,支持数组现在包含[1, 2, 3, 3]with len(a) == 3。数组中的最后一个元素通过正常的切片操作是不可见的,但保留其旧值。在第二次迭代中,切片再次缩短,因此支持数组现在[1, 3, 3, 3]是len(a) == 2。现在,当循环运行时,range表达式只计算一次,因此无论您在循环中进行什么更改,它始终会导致 4 次迭代。它还将从同一个支持数组返回结果,这解释了您看到的数字。
慕虎7371278
问题是a您在迭代时正在修改(删除元素),因此结果可能有点......令人惊讶。我的猜测是,你的第一个删除后,a是在内存中类似的东西:[1 2 3 3],所以a[2]是3和你的第二个删除后,a是类似的东西在内存:[1 3 3 3]等a[3]是3。因此,我的第一个建议是更改代码以使用传统for循环而不是范围,并且i仅在您不删除某些内容时才增加:package mainimport "fmt"func main() { a := []int{0, 1, 2, 3} for i := 0; i < len(a); { v := a[i] fmt.Printf("i: %d v: %d\n", i, v) fmt.Println("before", a) if v%2 == 0 { // delete a[i] a = append(a[:i], a[i+1:]...) } else { i++ } fmt.Println("after", a, "\n") } fmt.Println("final", a)}这是输出:i: 0 v: 0before [0 1 2 3]after [1 2 3]i: 0 v: 1before [1 2 3]after [1 2 3]i: 1 v: 2before [1 2 3]after [1 3] i: 1 v: 3 before [1 3] after [1 3] final [1 3]我的第二个建议是反转循环(从末尾迭代)以避免递增/递减的“特殊情况”:package mainimport "fmt"func main() { a := []int{0, 1, 2, 3} for i := len(a) - 1; i >= 0; i-- { v := a[i] fmt.Printf("i: %d v: %d\n", i, v) fmt.Println("before", a) if v%2 == 0 { // delete a[i] a = append(a[:i], a[i+1:]...) } fmt.Println("after", a, "\n") } fmt.Println("final", a)}这是输出:i: 3 v: 3 before [0 1 2 3] after [0 1 2 3] i: 2 v: 2 before [0 1 2 3] after [0 1 3] i: 1 v: 1 before [0 1 3] after [0 1 3] i: 0 v: 0 before [0 1 3] after [1 3] final [1 3]