请说出一下打印结果

  • 第一种

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package main

    import "fmt"

    func main() {
    sli := make([]int, 2, 3)
    sli[0] = 0
    sli[1] = 1

    res := changeSlice(sli)
    fmt.Printf("sli: %+v, res: %+v \n", sli, res)

    res[0] = 100

    fmt.Printf("sli: %+v, res: %+v \n", sli, res)

    }

    func changeSlice(s []int) []int {
    s = append(s, 3)
    return s
    }

    结果:

    1
    2
    3
    ☁  test2  go run main.go
    sli: [0 1], res: [0 1 3]
    sli: [100 1], res: [100 1 3]
    • 当sli传递给函数的时候,新建了切片s。在函数中给s进行了append一个元素,由于此时s的容量足够到,并没有生成新的底层数组。当修改返回的res的时候,res与sli共用了底层的数组,因此修改ret的原始,相应的也看到了slice的改变。
  • 第二种

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package main

    import "fmt"

    func main() {
    sli := make([]int, 2, 2)
    sli[0] = 0
    sli[1] = 1

    res := changeSlice(sli)
    fmt.Printf("sli: %+v, res: %+v \n", sli, res)

    res[0] = 100

    fmt.Printf("sli: %+v, res: %+v \n", sli, res)

    }

    func changeSlice(s []int) []int {
    s = append(s, 3)
    return s
    }

    结果:

    1
    2
    3
    4
    5
    ☁  test2  go run main.go
    sli: [0 1], res: [0 1 3]
    sli: [0 1], res: [100 1 3]


    • 函数中先改变s第一个元素的值,由于slice和s都共用了底层数组,因此无论原始切片slice还是ret,第一个元素都是-1.然后append操作之后,因为超出了s的容量,因此会新建底层数组,虽然s变量没变,但是他的底层数组变了,此时修改s第一个元素,并不会影响原始的slice切片。

总结

  • 切片底层本质是基于数组

  • append的是用来向切片添加数据的,当前切片容量够的时候,append生成的心切片依然和之前的切片共享底层数组,一旦当前切片的容量不够用的时候就会另起灶炉,生成新的底层数组。