切片的内部实现
切片可以理解为动态长度的数组。
切片的内部实现是由3部分构成:
- 指向底层数组的指针
- 长度:当前元素的个数,可以用
len
函数来获取 - 容量:最大存储空间的个数,可以用
cap
函数来获取
定义切片的基本语法为:
var 切片名 []数据类型
切片只定义的话是无法使用的,还需要用make
内置函数进行初始化才能进行数据的存取。切片定义和初始化更简洁的语法为:
slicename := make([]datatype,length,capacity)
// 示例,定义并初始化已问过长度为3、容量为5的切片
// 虽然容量为5,但是只会在内存中开辟长度为3的数组。
slice1 := make([]int,3,5)
示例代码:基础切片用法
package main
import "fmt"
func main(){
var slice []string
fmt.Println(len(slice)) // 0
fmt.Println(cap(slice)) // 0
fmt.Printf("%#v", slice) // []string(nil)
fmt.Println()
slice = make([]string, 6)
slice[0] = "Hello"
slice[5] = "world"
fmt.Printf("%#v\n", slice) // []string{"Hello", "", "", "", "", "world"}
slice2 := []int{1,2,3,4,5}
slice1 := slice2
slice1[0] = 9
fmt.Println(slice2) // [9 2 3 4 5]
slice3 := make([]int,3,10)
fmt.Println(len(slice3)) // 3
fmt.Println(cap(slice3)) // 10
fmt.Println(slice3) // [0 0 0]
slice3[0] = 1
slice3[1] = 2
slice3[2] = 3
fmt.Println(slice3) // [1 2 3]
}
切片的切割
切割切片的基本语法:
slice[i:j] //从slice下表为i(i从0开始)的元素开始切,切片长度为 j-i
slice[i:j:k] //从slice下表为i(i从0开始)的元素开始切,切片长度为 j-i,容量为 k-i
slice[i:] //从slice下表为i(i从0开始)的元素开始切,切割到末尾
slice[:j] //从开头开始切,切到下标为j-1的元素,不包含j
slice[:] //从头切到尾,等同slice复制
将切片切割为两个切片时,它们共享底层数组,因此修改其中一个,也会影响到另外一个切片。
切片的扩容
可以通过append
函数实现切片的扩容。append
函数有两个参数:第一个参数是将被处理的切片,另一个参数是要追加的参数。
append
参数会返回一个扩容后的新切片。
切片作为函数的参数
切片如果作为函数的参数,那么函数内部的切片参数和外部的切片参数实际上的底层数组是同一个对象,因此函数内部修改切片的值会影响外部的参数切片值。
// 切片作为函数的参数
package main
import "fmt"
func changes(slice []int) {
slice[1] = 99
}
func main() {
slice := []int{1,2,3,4,5}
slice2 := []int{6,7,8,9,10}
// 合并
slice = append(slice, slice2...)
fmt.Println(slice) // [1,2,3,4,5,6,7,8,9,10]
changes(slice)
fmt.Println(slice) // 1,99,3,4,5,6,7,8,9,10
}