切片相关操作

Go语言切片是对数组的抽象。数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片(”动态数组”),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

需要说明,slice 并不是数组或数组指针。它通过内部指针和相关属性引用数组片段,以实现变长方案

第一种切片定义和初始化

1
2
3
4
5
6
7
8
9
10
func main() {
var slice []int
fmt.Printf("%#v", slice) // 切片定义后未赋值的默认值是[]int(nil) nil

slice = []int{}
fmt.Printf("%#v", slice) // 切片空值初始化为 []int{}

slice = []int{1, 2, 3} // 切片可以任意长度
fmt.Println(slice)
}

第二种,通过索引指定切片的初始化值,未指定初始值为默认值

1
2
3
4
func main() {
name := []string{1: "zhangsan", 3: "王五"}
fmt.Printf("%#v", name) // {"", "zhangsan", "", "王五"}
}

第三种,通过make函数定义切片再赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func main() {
var names []string
// make两个参数的切片,第一个参数为切片数据类型,第二个参数为切片长度
names = make([]string, 5)
fmt.Printf("%#v", names) // {"", "", "", "", ""}

// make三个参数切片,第一个参数为切片数据类型,第二个参数为切片长度,第三个参数为容量
var slice1 []string
slice1 = make([]string, 5, 10)
fmt.Printf("%#v", slice1)

// 切片赋值给另一个切片
var slice2 []int = make([]int,3)
fmt.Printf("%#v",slice2) // {0, 0, 0}
}

第四种,空接口切片,可以接收任意参数类型

1
clice := make([]interface{},0)

向切片中添加修改元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func main() {
names := make([]string, 3)

// 修改切片指定索引的元素
names[0] = "张三"
names[1] = "李四"
names[2] = "王五"
fmt.Printf("%#v\n", names) // {"张三", "李四", "王五"}
fmt.Println(len(names), cap(names)) // 3 3 当没有指定容量时,容量和长度是一样的


// 向切片中添加一个元素,注意这里变量名和切片名要一致
names = append(names, "赵六")
fmt.Printf("%#v\n",names) // {"张三", "李四", "王五", "赵六"}
fmt.Println(len(names), cap(names)) // 4 6前面定义names切片长度为3,append前已经存满3个元素,当容量不够时会重新申请一个长度为3的切片来存放,故切片总容量为6
}

删除切片中的元素

go语言暂时没有原生直接支持删除切片的方法,但是可以对切片进行切分来达到删除切片的目的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func main() {
nums := []int{1,2,3,4,5}
fmt.Printf("%d\n",nums) // [1 2 3 4 5]

// start == 0 start可以省略
// end = len(nums) end可以省略
// 移除切片第一个元素
nums = nums[1:]
fmt.Println(nums) // [2 3 4 5]

// 移除切片最后一个元素
nums1 := []int{1,2,3,4,5}
nums1 = nums1[:len(nums1)-1]
fmt.Println(nums1) // [1 2 3 4]

// 移除切片中间的元素
nums2 := []int{1,2,3,4,5}
nums22 := append(nums2[:2],nums2[3:]...)
fmt.Println(nums22) // [1 2 4 5]
}

遍历切片中的元素

1
2
3
4
5
6
7
8
9
10
11
12
13
func main() {
names := []string{"张三","李四","王五"}

// 通过for条件遍历元素
for i:=0; i<len(names);i++{
fmt.Println(i,names[i])
}

// 通过for range遍历切片元素
for k,v:= range names{
fmt.Println(k,v)
}
}

切片之间的复制

两个切片类型相同、长度相同时复制

1
2
3
4
5
6
7
8
9
func main() {
A := []string{"a", "b", "c"}
B := []string{"x", "y", "z"}

// 将B切片中的元素复制到A切片中,copy(目的,源),完全替换目的索引中的元素
copy(A, B)
fmt.Printf("%#v\n",A) // {"x", "y", "z"}
fmt.Printf("%#v\n",B) // {"x", "y", "z"}
}

当源切片元素比目的切片元素多时复制

1
2
3
4
5
6
7
8
9
10
func main() {
A := []string{"a", "b", "c"}
B := []string{"x", "y", "z","m"}

// 两个切片类型相同、长度相同时复制
// 将B切片中的元素复制到A切片中,copy(目的,源),当源元素比目的切片元素多时只替换源中相同长度的元素。
copy(A, B)
fmt.Printf("%#v\n",A) // 复制后目的元素:{"x", "y", "z"}
fmt.Printf("%#v\n",B) // 源元素:{"x", "y", "z", "m"}
}

当源切片比目的切片元素少时复制

1
2
3
4
5
6
7
8
9
10
func main() {
A := []string{"a", "b", "c"}
B := []string{"x", "y"}

// 两个切片类型相同、长度相同时复制
// 将B切片中的元素复制到A切片中,copy(目的,源),当源元素比目的切片元素少时,只复制源中已有的元素
copy(A, B)
fmt.Printf("%#v\n", A) // 复制后目的元素:{"x", "y", "c"}
fmt.Printf("%#v\n", B) // 源元素:{"x", "y"}
}