美文网首页
切片遍历的坑

切片遍历的坑

作者: 马晓钧 | 来源:发表于2020-06-17 17:11 被阅读0次

    我们正常对于一个切片进行遍历不会有啥坑的,会出现有坑的点是,在遍历的过程中想对原切片数据进行修改,其中包括修改原切片中某个值,对原切片增加元素,删除元素等。

    原理

    1. 在range的时候,并不会对切片中的元素直接操作,而是新创建一块地址,然后把切片中每个元素的地址拷贝到这块新地址当中,这块地址在切片遍历期间不会发生任何变化。(核心点)
    2. 在range开始的时候,就会把长度记下来,期间不管这个切片发生了什么变化,都会遍历这么长。
    3. 在range过程中删除的时候,如果说index超出了切片的大小,会panic,在没有超出的情况下,删除几个元素,指针会向移动几位,即使是删除之前的元素,依然会向后移动。当后面没有元素了,但还在遍历中的时候,删除了几个元素,指针就会从后往前退几位,再重新进行遍历。即使在删除过程中新增的元素,永远也不会遍历到这个。


      image.png

    场景1:range过程中修改元素

    切片中是非指针

    修改e中的值,并不会改变原来切片中的值。

    func main() {
        num0 := 0
        num1 := 1
        num2 := 2
        num3 := 3
    
        slice := []int{num0, num1, num2, num3}
        for _, v := range slice {
            if v == 1 {
                v = 100
            }
        }
        for k, v := range slice {
            fmt.Println("k:", k, "v:", v)
        }
    }
    
    k: 0 v: 0
    k: 1 v: 1
    k: 2 v: 2
    k: 3 v: 3
    
    切片中是指针或结构体
    func main() {
        num0 := 0
        num1 := 1
        num2 := 2
        num3 := 3
    
        slice := []*int{&num0, &num1, &num2, &num3}
        for _, v := range slice {
            if *v == 1 {
                *v = 100
            }
        }
        for k, v := range slice {
            fmt.Println("k:", k, "v:", *v)
        }
    }
    
    k: 0 v: 0
    k: 1 v: 100
    k: 2 v: 2
    k: 3 v: 3
    

    场景2:新增元素

    append
    func main() {
        num0 := 0
        num1 := 1
        num2 := 2
        num3 := 3
    
        slice := []int{num0, num1, num2, num3}
        for _, v := range slice {
            fmt.Println(v)
            if v == 2 {
                slice = append(slice, 4)
            }
        }
        for k, v := range slice {
            fmt.Println("k:", k, "v:", v)
        }
    }
    
    0
    1
    2
    3
    k: 0 v: 0
    k: 1 v: 1
    k: 2 v: 2
    k: 3 v: 3
    k: 4 v: 4
    
    赋新值
    func main() {
        num0 := 0
        num1 := 1
        num2 := 2
        num3 := 3
    
        slice := []int{num0, num1, num2, num3}
        for _, v := range slice {
            fmt.Println(v)
            if v == 2 {
                slice = []int{5, 6, 7, 8}
            }
        }
        for k, v := range slice {
            fmt.Println("k:", k, "v:", v)
        }
    }
    
    0
    1
    2
    3
    k: 0 v: 5
    k: 1 v: 6
    k: 2 v: 7
    k: 3 v: 8
    
    赋空
    func main() {
        num0 := 0
        num1 := 1
        num2 := 2
        num3 := 3
    
        slice := []int{num0, num1, num2, num3}
        for _, v := range slice {
            fmt.Println(v)
            if v == 2 {
                slice = nil
            }
        }
        for k, v := range slice {
            fmt.Println("k:", k, "v:", v)
        }
    }
    
    0
    1
    2
    3
    

    场景3:删除元素

    删除切片index内的元素
    func main() {
      num0 := 0
        num1 := 1
        num2 := 2
        num3 := 3
        num4 := 4
        num5 := 5
    
        slice := []*int{&num0, &num1, &num2, &num3, &num4, &num5}
        for _, v := range slice {
            fmt.Println(*v)
            if *v == 0 {
          //删除前三位
                slice = append(slice[:0], slice[3:]...)
            }
        }
        for k, v := range slice {
            fmt.Println("k:", k, "v:", *v)
        }
    }
    
    0
    4
    5
    3
    4
    5
    k: 0 v: 3
    k: 1 v: 4
    k: 2 v: 5
    
    删除切片index外的元素
    func main() {
      num0 := 0
        num1 := 1
        num2 := 2
        num3 := 3
        num4 := 4
        num5 := 5
    
        slice := []*int{&num0, &num1, &num2, &num3, &num4, &num5}
        for _, v := range slice {
            fmt.Println(*v)
            if *v == 0 {
          //删除第10位
                slice = append(slice[:10], slice[11:]...)
            }
        }
        for k, v := range slice {
            fmt.Println("k:", k, "v:", *v)
        }
    }
    //直接panic的
    

    相关文章

      网友评论

          本文标题:切片遍历的坑

          本文链接:https://www.haomeiwen.com/subject/zgbsxktx.html