数组的特点:

    • 数组的长度在定义之后无法再次修改;
    • 数组是值类型,每次传递都将产生一份副本。

    显然这种数据结构无法完全满足开发者的真实需求。
    Go语言提供了数组切片(slice)这个非常酷的功能来弥补数组的不足。
    数组切片就像一个指向数组的指针,实际上它拥有自己的数据结构,而不仅仅是个指针。

    数组切片的数据结构可以抽象为以下3个变量:

    • 一个指向原生数组的指针;
    • 数组切片中的元素个数;
    • 数组切片已分配的存储空间。

    数据切片 和 数组 之间的关系 类似于 C++中的std::vector和数组
    数组切片添加了一系列管理功能,可以随时动态扩充存放空间,
    并且可以被随意传递而不会导致所管理的元素被重复复制。

    1. package main
    2. import "fmt"
    3. func main() {
    4. var myArray [10] int = [10]int {1,2,3,4,5,6,7,8,9,10}
    5. var mySlice []int = myArray[:5]
    6. for _, v := range myArray {
    7. fmt.Print(v, " ")
    8. }
    9. fmt.Println()
    10. for _, v := range mySlice {
    11. fmt.Print(v, " ")
    12. }
    13. }

    Go语言提供的内置函数 make() 可以用于灵活地创建数组切片。

    1. # 创建一个初始元素个数为5的数组切片,元素初始值为0:
    2. mySlice1 := make([]int, 5)
    3. 创建一个初始元素个数为5的数组切片,元素初始值为0,并预留10个元素的存储空间:
    4. mySlice2 := make([]int, 5, 10)
    5. 直接创建并初始化包含5个元素的数组切片:
    6. mySlice3 := []int{1, 2, 3, 4, 5}

    注: [10]int 算是数组, []int 才是切片
    可动态增减元素是数组切片比数组更为强大的功能。与数组相比,数组切片多了一个存储能力(capacity)的概念,即元素个数和分配的空间可以是两个不同的值。

    1. package main
    2. import "fmt"
    3. func main() {
    4. mySlice := make([]int, 5, 10)
    5. fmt.Println(len(mySlice)) // 切片的长度5
    6. fmt.Println(cap(mySlice)) // 切片的容量10
    7. fmt.Println(mySlice) // [0 0 0 0 0]
    8. mySlice = append(mySlice, 1, 2, 3) // 往切片后追加
    9. fmt.Println(mySlice) // [0 0 0 0 0 1 2 3]
    10. mySlice2 := []int{8, 9, 10}
    11. mySlice = append(mySlice, mySlice2...) // 加上省略号相当于把切片解包
    12. fmt.Println(mySlice) // [0 0 0 0 0 1 2 3 8 9 10]
    13. }

    数组切片支持Go语言的另一个内置函数 copy() ,用于将内容从一个数组切片复制到另一个数组切片。如果加入的两个数组切片不一样大,就会按其中较小的那个数组切片的元素个数进行复制。

    1. // 注: copy(dst, src)
    2. slice1 := []int{1, 2, 3, 4, 5}
    3. slice2 := []int{5, 4, 3}
    4. copy(slice2, slice1) // 只会复制slice1的前3个元素到slice2中
    5. copy(slice1, slice2) // 只会复制slice2的3个元素到slice1的前3个位置


    1. func main() {
    2. a := []int{7, 8, 9}
    3. fmt.Printf("%+v\n", a)
    4. ap(a)
    5. fmt.Printf("%+v\n", a)
    6. app(a)
    7. fmt.Printf("%+v\n", a)
    8. }
    9. func ap(a []int) {
    10. a = append(a, 10)
    11. }
    12. func app(a []int) {
    13. a[0] = 1
    14. }

    [7 8 9] [7 8 9] [1 8 9]

    因为append导致底层数组重新分配内存了,append中的a这个slice的底层数组和外面不是一个,并没有改变外面的。