数组定义长度后是无法修改的,数组的长度是数组类型本身的一部分,长度是数组内的一个内置常量,因此我们不能对数组进行一个增删操作。显然数组这种不灵活的特性是不能满足日常开发需求的,因此golang提供了另一种数据类型(slice)数组切片来你补数组的不足。数组切片是一个能对元素进行增删的数组,它的底层就是基于数组实现的。

数组切片的定义

在go中,定义数组切片稍微与定义数组不同,数组是需要指定长度和类型的,数组切片只需要指定类型不需要指定长度。

  1. package main
  2. import "fmt"
  3. func main() {
  4. // 数组
  5. var arr = [5]int{1, 2, 3, 4, 5}
  6. // 切片
  7. var _slice = []int{1, 2, 3, 4, 5}
  8. fmt.Println(arr)
  9. fmt.Println(_slice)
  10. }
切片是一个可变长度同一类型元素的集合,切片的长度可以随着元素增长而增长(不会因为减少而减少),不过数组底层管理依然使用数组来管理元素。切片是数组的一层封装,基于数组为其提供一系列管理功能,可以动态拓展存储空间。

创建数组切片

创建数组切片的方法主要有三种 —— 基于数组基于数组切片直接创建

基于数组

数组切片可以基于一个已经存在的数组创建。数组可以看做是切片的底层数组,切片则是其某个连续片段的引用。切片可以局域数组的一部分创建也可以基于一整个创建,甚至可以创建一个比原数组更大的切片。

package main

import "fmt"

func main() {
    // 创建一个数组
    nums := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

    // 基于数组片段创建切片
    slice1 := nums[0:3]
    slice2 := nums[5:9]

    // 基于数组全部创建切片
    sliceAll := nums[:]

    fmt.Println(slice1)
    fmt.Println(slice2)
    fmt.Println(sliceAll)
}
切片的底层结构主要分为三个部分
  • 指针:指向底层数组起始下标
  • 长度:对应切片中元素个数,可通过len函数获取切片长度
  • 容量:切片的起始位置到底层数组的结尾位置,可通过cap函数来获取容量

    基于切片

    类似于基于数组创建切片,也可以基于切片来创建切片 ``` package main

import “fmt”

func main() { // 创建一个数组 nums := […]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

// 基于数组片段创建切片
slice1 := nums[0:3]
slice2 := nums[5:9]

// 基于数组全部创建切片
sliceAll := nums[:]

// 基于切片创建切片
slice3 := slice1[:2]

fmt.Println(slice1)
fmt.Println(slice2)
fmt.Println(sliceAll)
fmt.Println(slice3)

}

    需要注意的是在切片创建时,指定的长度不可超出原底层数组的容量。如nums初始长度为10,如果基于slice1创建切片,长度就不允许超出10。
<a name="wTDPY"></a>
### 直接创建
并非一定要事先准备一个数组才能创建数组切片,Go 语言提供的内置函数 make() 可以用于灵活地创建数组切片。下面的例子示范了直接创建数组切片的各种方法:

package main

import “fmt”

func main() { // 创建一个数组 nums := […]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

// 基于数组片段创建切片
slice1 := nums[0:3]
slice2 := nums[5:9]

// 基于数组全部创建切片
sliceAll := nums[:]

// 基于切片创建切片
slice3 := slice1[:2]

// 直接创建,创建初始长度为10的切片。
slice4 := make([]int, 10)

// 直接创建,创建初始长度为10,容量为20的切片。
slice5 := make([]int, 10, 20)

// 还可以直接创建并初始化包含 5 个元素的数组切片
slice6 := []int{1, 2, 3, 4,5}

fmt.Println(slice1)
fmt.Println(slice2)
fmt.Println(sliceAll)
fmt.Println(slice3)
fmt.Println(slice4)
fmt.Println(slice5, cap(slice5))
fmt.Println(slice6, cap(slice6))

}

<a name="Lj5ef"></a>
## 遍历数组切片
操作数组元素的所有方法都适用于数组切片,比如数组切片也可以按下标读写元素,用 len() 函数获取元素个数,并支持使用 range 关键字来快速遍历所有元素。

package main

import “fmt”

func main() { // 创建一个数组 nums := […]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

// 基于数组片段创建切片
slice1 := nums[0:3]
slice2 := nums[5:9]

// 基于数组全部创建切片
sliceAll := nums[:]

// 基于切片创建切片
slice3 := slice1[:2]

// 直接创建,创建初始长度为10的切片。
slice4 := make([]int, 10)

// 直接创建,创建初始长度为10,容量为20的切片。
slice5 := make([]int, 10, 20)

// 还可以直接创建并初始化包含 5 个元素的数组切片
slice6 := []int{1, 2, 3, 4, 5}

fmt.Println(slice1)
fmt.Println(slice2)
fmt.Println(sliceAll)
fmt.Println(slice3)
fmt.Println(slice4)
fmt.Println(slice5, cap(slice5))
fmt.Println(slice6, cap(slice6))

for i := 0; i < len(nums); i++ {
    fmt.Println(nums[i])
}

for i, v := range nums {
    fmt.Println(i, v)
}

} ```