本文最后更新于 2024年10月15日 下午
在go语言中,切片是对数组的抽象,数组在声明时指定了长度之后就不可再进行改变,在特定场景下数组就不适用,所以就有了切片类型,切片就是“动态数组”,和数组相比,切片的长度是不固定的,可以在切片后面追加元素,长度自动扩容。
切片定义
定义切片和定义数组很像,区别就是定义一个切片不需要指定长度。
切片还可以使用make函数定义。
1
| make([]T, length, capacity)
|
make函数有三个参数:
- 第一个参数为切片类型,可以是
[]int,[]string,[]float32
等。
- 第二个参数为切片初始长度。
- 第三个为切片容量,该参数为可选参数。
切片初始化
一个切片在初始化之前为空切片(nil),长度为0,可以在声明切片时直接初始化切片,如下表示声明一个int切片,初始化值为{1, 2, 3}
初始化为数组的引用,假设有一个数组arr,在初始化为数组的引用时,通过开始索引和结束索引控制初始化的切片大小和切片内元素个数。
1 2 3 4
| s := arr[startIndex:endIndex] s := arr[startIndex:] s := arr[:endIndex] s := arr[:]
|
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package main
import "fmt"
func main() { arr := [5]int{1, 2, 3, 4, 5} s1 := arr[:] s2 := arr[2:] s3 := arr[:3] s4 := arr[1:4] fmt.Println(s1) fmt.Println(s2) fmt.Println(s3) fmt.Println(s4) }
|
运行结果:
append和copy
append表示在一个切片的末尾追加元素。
copy表示复制一个切片里面的元素到另一个切片。
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13
| package main
import "fmt"
func main() { s := []int{1,2,3} fmt.Println("切片s:",s) s = append(s, 4) fmt.Println("切片s:",s) s1 := make([]int, 4) copy(s1, s) fmt.Println("切片s1:",s1) }
|
运行结果:
切片截取
切片截取使用中括号[]
,通过指定需要截取的开始索引和结束索引。
代码示例:
1 2 3 4 5 6 7 8 9 10 11
| package main
import "fmt"
func main() { s := []int{1,2,3,4,5} fmt.Println("完整切片:", s) fmt.Println("s[1:3]:", s[1:3]) fmt.Println("s[:4]:", s[:4]) fmt.Println("s[2:]:", s[2:]) }
|
运行结果:
len和cap
长度和容量区别:
- 长度:长度表示切片中实际存储的元素个数
- 容量:容量表示切片底层使用的数组的大小
当定义一个切片时,如果没有通过make方法指定cap,则底层会申请一个和切片长度一样的数组,这个数组的大小就是cap,当使用append朝切片中追加元素时,如果追加元素后新的len小于cap,则底层数组不会改变,当新的len大于cap时,底层就会重新申请一个数组,且数组的长度为cap * 2,然后将之前数组的元素全部复制到新数组中。
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package main
import "fmt"
func main() { s := make([]int, 3) fmt.Printf("len:%d, cap:%d \n", len(s), cap(s))
s = append(s, 1) fmt.Printf("len:%d, cap:%d \n", len(s), cap(s))
s = append(s, 1) fmt.Printf("len:%d, cap:%d \n", len(s), cap(s))
s = append(s, 1) fmt.Printf("len:%d, cap:%d \n", len(s), cap(s))
s = append(s, 1) fmt.Printf("len:%d, cap:%d \n", len(s), cap(s)) }
|
运行结果: