八、切片(slice)
1.
切片是go语言中特有的数据类型
数组有特定用处,但数组的长度是固定的,所以在go中并不常用,相反,切片确实随处可见的。切片是建立在数组之上的抽象,提供了便捷和更强大的能力。
切片是对数组一个连续片段的引用,所以切片是一个引用类型。这个片段可以是整个数组,也可以是由起始和终止索引标识的一些项的子集。注意:终止索引标识的项不在切片内,切片提供了相关数组的一个动态窗口。
package main
import "fmt"
func main() {
//定义数组
var arr = [4]int{2, 43, 56, 34}
//定义切片
//起始索引为1,终止索引为3,且不包含3
var slice []int = arr[1:3]
//另一种定义切片方式
slice1 := arr[1:3]
//打印
fmt.Println(arr)
fmt.Println(slice)
fmt.Println(slice1)
//获取切片slice元素个数
fmt.Println("切片slice元素个数为:", len(slice))
//获取切片slice容量,容量可以动态变化
fmt.Println("切片slice容量为:", cap(slice)) //调用builtin包下的cap函数获取容量
}
输出:
切片包含三部分:底层数组指针、切片元素个数、切片容量
2.切片定义:
方式一:建立在已经定义好的数组之上
方式二:通过make内置函数来创建切片,
make函数基本语法: var切片名[type = make([],len,cap())]
ps:使用make函数底层创建数组,对外不可见,所以不能直接操作数组,而需要通过slice间接访问各个元素。
package main
import "fmt"
func main() {
//make函数1.表示数据类型,2.切片长度,3.切片容量
slice := make([]int, 4, 12)
fmt.Println(slice)
}
方式三:使用原理与make函数类似,要通过slice间接操作。
slice2 := []int{1, 5, 7, 35, 89}
fmt.Println(slice2)
fmt.Println("切片2对应的长度为:", len(slice2))
fmt.Println("切片2对应的容量为:", cap(slice2))
3.切片遍历
两种方式:第一种普通for循环,第二种for-range循环。
package main
import (
"fmt"
)
func main() {
//定义切片
slice := []int{12, 35, 57, 46, 2435}
//方式一:普通for循环
for i := 0; i < len(slice); i++ {
fmt.Printf("slice[%v]=%v\n", i, slice[i])
}
fmt.Println("-----------------------------------")
//方式二:for range循环
for k, v := range slice {
fmt.Printf("下表为%v的元素为%v\n", k, v)
}
}
4.切片注意事项
切片定义后不能直接使用,需要引用一个数组或者make一个空间供其使用。
切片不能越界。
简写方式
var slice = intarr[:2] ==var slice = intarr[start:2]
var slice = intarr[1:] ==var slice = intarr[1:end]
var slice = intarr[:] ==var slice = intarr[start:end]
切片还可以继续切片
package main
import (
"fmt"
)
func main() {
var intarr = [8]int{1, 3, 57, 78, 24, 56, 35, 24}
var slice = intarr[1:5]
fmt.Println(slice) //[3,57,78,24]
var slice2 = slice[1:3]
fmt.Println(slice2) //[57,78]
slice2[0] = 25
slice2[1] = 35
fmt.Println(intarr) //将intarr数组对应位置的值也改变了,因为这与切片内存有关
fmt.Println(slice) //同理
fmt.Println(slice2)
}
输出:
切片可以动态增长
package main
import "fmt"
func main() {
var intarr = [7]int{1, 34, 56, 35, 14, 78, 98}
var slice = intarr[1:2] //34
fmt.Println(slice)
slice2 := append(slice, 45, 242)
fmt.Println(slice2)
//1.首先建立一个新数组,然后把老数组中的元素34复制到新数组,然后在新数组中追加元素45,242
//2.slice2底层数组指向的是新数组
//3.如果想把追加元素放到原来的切片,那么用slice来接收就可以 slice:=append(slice,45,242)
//4.底层的新数组同样不能直接维护,需要通过切片间接操作
//5.可以在切片后面追加切片
slice3 := []int{1, 2, 3}
slice = append(slice, slice3...) //...必写
fmt.Println(slice)
}
切片的拷贝
package main
import "fmt"
func main() {
//定义一个切片
var a = []int{1, 34, 56}
//再定义一个切片
var b = make([]int, 5)
copy(b, a) //将a切片对应数组的元素赋值到b切片对应数组的位置
fmt.Println(b)
}
输出: