Skip to content

1.golang切片

数组是固定长度,可以容纳相同数据类型的元素的集合。当长度固定时,使用还是带来一些限制,比如:我们申请的长度太大浪费内存,太小又不够用。

由于上述原因,我们有了go语言的切片,可以吧切片理解为,可变长度的数组,其实它底层就是使用数组实现的,增加了自动扩容功能。切片(Slice)是一个拥有相同类型元素的可变长度的序列。

1.1切片语法

声明一个切片和声明一个数组类似,只要不添加长度就可以

go
var identifier []type
var identifier []type

切片是引用类型,可以使用make函数来创建切片

go
var slice1 []type=make([]type,len)
也可以简写为
slice1 := make([]type,len)
var slice1 []type=make([]type,len)
也可以简写为
slice1 := make([]type,len)

也可以指定容量,其中capacity为可选参数。

go
make([]T, length, capacity)
make([]T, length, capacity)

这里len是数组的长度并且也是切片的初始长度

go
func sliceFuncs() {
	//
	var s1 []int
	fmt.Printf("s1:%v\n", s1)

	//分配内存
	var s2 = make([]int, 2)
	fmt.Printf("s2:%v\n", s2)
}
func sliceFuncs() {
	//
	var s1 []int
	fmt.Printf("s1:%v\n", s1)

	//分配内存
	var s2 = make([]int, 2)
	fmt.Printf("s2:%v\n", s2)
}

1.2切片长度和容量

切片拥有自己的长度和容量,我们可以通过使用内置的len()函数求长度,使用内置的cap()函数求切片的容量。

go
func SliceCapFunc() {
	var s1 = []int{1, 2, 3}
	fmt.Printf("len(s1):%v\n", len(s1))
	fmt.Printf("cap(s1):%v\n", cap(s1))
}
func SliceCapFunc() {
	var s1 = []int{1, 2, 3}
	fmt.Printf("len(s1):%v\n", len(s1))
	fmt.Printf("cap(s1):%v\n", cap(s1))
}

1.3切片初始化

切片的初始化方法很多,可以直接初始化,也可以使用数组初始化等。

直接初始化

go
func SliceCapFunc() {
	var s1 = []int{1, 2, 3}
	fmt.Printf("len(s1):%v\n", len(s1))
	fmt.Printf("cap(s1):%v\n", cap(s1))

	//直接初始化
	println("----初始化----")
	s2 := []int{1, 2, 3}
	fmt.Printf("s2:%v\n", s2)
}
func SliceCapFunc() {
	var s1 = []int{1, 2, 3}
	fmt.Printf("len(s1):%v\n", len(s1))
	fmt.Printf("cap(s1):%v\n", cap(s1))

	//直接初始化
	println("----初始化----")
	s2 := []int{1, 2, 3}
	fmt.Printf("s2:%v\n", s2)
}

使用数组方式初始化

go
func SliceCapFunc() {

	//数组方式初始化
	println("----组方式初始化----")
	arr := [...]int{1, 2, 3, 4, 5, 6}
    //取所有数据[:]
	s3 := arr[:]
	fmt.Printf("s3:%v\n", s3)
}
func SliceCapFunc() {

	//数组方式初始化
	println("----组方式初始化----")
	arr := [...]int{1, 2, 3, 4, 5, 6}
    //取所有数据[:]
	s3 := arr[:]
	fmt.Printf("s3:%v\n", s3)
}

1.4使用数组的部分元素初始化(切片表达式)

切片的底层就是一个数组,所以我们可以基于数组通过切片表达式得到切片。切片表达式中的low和high表示一个索引范围(左包含、右不包含),的到的切片长度=high-low,容量等于得到切片的底层数组的容量。

go
func sliceInit() {
	var s1 = []int{1, 2, 3, 4, 5, 6}
	s2 := s1[0:3]
	fmt.Printf("s2:%v\n", s2)

	s3 := s1[3:]
	fmt.Printf("s3:%v\n", s3)

	s4 := s1[2:5]
	fmt.Printf("s4:%v\n", s4)

	println("----------取所有元素------------")
	s5 := s1[:]
	fmt.Printf("s5:%v\n", s5)
}
func sliceInit() {
	var s1 = []int{1, 2, 3, 4, 5, 6}
	s2 := s1[0:3]
	fmt.Printf("s2:%v\n", s2)

	s3 := s1[3:]
	fmt.Printf("s3:%v\n", s3)

	s4 := s1[2:5]
	fmt.Printf("s4:%v\n", s4)

	println("----------取所有元素------------")
	s5 := s1[:]
	fmt.Printf("s5:%v\n", s5)
}

空切片

一个切片在未初始化之前默认为nil,长度为0,容量为0

go
func kongSlice(){
	println("----------空切片------------")
	var kong []int
	fmt.Println(kong == nil)
	fmt.Printf("len(kong):%v,cap(kong):%v", len(kong), cap(kong))
}
func kongSlice(){
	println("----------空切片------------")
	var kong []int
	fmt.Println(kong == nil)
	fmt.Printf("len(kong):%v,cap(kong):%v", len(kong), cap(kong))
}

2.切片遍历

切片的遍历和数组的遍历类似,可以使用for循环索引遍历,或者for range循环

2.1for循环索引遍历

go
func SliceForFunc() {
	s1 := []int{1, 2, 3, 4, 5, 6}
	for i := 0; i < len(s1); i++ {
		fmt.Printf("s1[%d]:%v\n", i, s1[i])
	}
}
func SliceForFunc() {
	s1 := []int{1, 2, 3, 4, 5, 6}
	for i := 0; i < len(s1); i++ {
		fmt.Printf("s1[%d]:%v\n", i, s1[i])
	}
}

2.2for range循环遍历

go
func SliceForFunc() {
	s1 := []int{1, 2, 3, 4, 5, 6}
	println("----------for range------------")
	for key, v := range s1 {
		fmt.Printf("key[%d]:%v\n", key, v)
	}
}
func SliceForFunc() {
	s1 := []int{1, 2, 3, 4, 5, 6}
	println("----------for range------------")
	for key, v := range s1 {
		fmt.Printf("key[%d]:%v\n", key, v)
	}
}

3.切片元素的添加和删除

切片是一个动态数组,可以使用append()函数添加元素,go语言中并没有删除切片元素的专用方法,我们可以使用切片本身的特性来删除元素。由于,切片是引用类型,通过赋值的方式,会修改原有内容,go提供了copy()函数来拷贝切片。

3.1添加元素

go
func sliceAppendFunc() {
	s1 := []int{}
	s1 = append(s1, 1)
	s1 = append(s1, 2)
	s1 = append(s1, 3, 4, 5, 6) //添加多个元素
	fmt.Printf("s1: %v\n", s1)
	println("----------添加另一个切片---------")
	s3 := []int{1, 2, 3}
	s4 := []int{5, 6}
	s4 = append(s4, s3...)
	fmt.Printf("s4: %v\n", s4)

}
func sliceAppendFunc() {
	s1 := []int{}
	s1 = append(s1, 1)
	s1 = append(s1, 2)
	s1 = append(s1, 3, 4, 5, 6) //添加多个元素
	fmt.Printf("s1: %v\n", s1)
	println("----------添加另一个切片---------")
	s3 := []int{1, 2, 3}
	s4 := []int{5, 6}
	s4 = append(s4, s3...)
	fmt.Printf("s4: %v\n", s4)

}

3.2删除

go
func sliceDelFunc() {
	s2 := []int{1, 2, 3, 4, 5, 6}
	s2 = append(s2[:2], s2[3:]...)
	fmt.Printf("s2: %v\n", s2)
}
func sliceDelFunc() {
	s2 := []int{1, 2, 3, 4, 5, 6}
	s2 = append(s2[:2], s2[3:]...)
	fmt.Printf("s2: %v\n", s2)
}

公式:要从切片a中删除索引为index的元素,操作方法是a=append(a[:index],a[index+1]...)

3.3更新值

重新赋值即可

go
func sliceUpdateFunc() {
	s2 := []int{1, 2, 3, 4, 5, 6}
	s2[1] = 100
	fmt.Printf("s2: %v\n", s2)
}
func sliceUpdateFunc() {
	s2 := []int{1, 2, 3, 4, 5, 6}
	s2[1] = 100
	fmt.Printf("s2: %v\n", s2)
}

3.4查询

go
func sliceQueryFunc() {
	s2 := []int{1, 2, 3, 4, 5, 6}
	var key = 2
	for i, v := range s2 {
		if v == key {
			fmt.Printf("i2索引值: %v\n", i)
		}
	}
}
func sliceQueryFunc() {
	s2 := []int{1, 2, 3, 4, 5, 6}
	var key = 2
	for i, v := range s2 {
		if v == key {
			fmt.Printf("i2索引值: %v\n", i)
		}
	}
}

3.5copy

go
func sliceCopyFunc() {
	s1 := []int{1, 2, 3, 4, 5, 6}
	s2 := s1
	s1[0] = 100
	fmt.Printf("s1: %v\n", s1)
	fmt.Printf("s2: %v\n", s2)
	println("----------------")
	s3 := make([]int, 6)
	copy(s3, s1)
	s3[0] = 200
	fmt.Printf("s3: %v\n", s3)
}
func sliceCopyFunc() {
	s1 := []int{1, 2, 3, 4, 5, 6}
	s2 := s1
	s1[0] = 100
	fmt.Printf("s1: %v\n", s1)
	fmt.Printf("s2: %v\n", s2)
	println("----------------")
	s3 := make([]int, 6)
	copy(s3, s1)
	s3[0] = 200
	fmt.Printf("s3: %v\n", s3)
}