go语言渐入佳境[13]-切片
1、切片可以修改大小
2、切片的拷贝不是单纯值的拷贝,一个切片指向了一个数组
1
2
3
4
5
6
7
//切片的声明1 //nil
var slice1 []int
//切片的声明2
var slice2 []int = make([]int,5)
var slice3 []int = make([]int,5,7)
numbers:= []int{1,2,3,4,5,6,7,8}
切片截取
1
2
3
4
5
6
7
8
numbers:= []int{1,2,3,4,5,6,7,8}
//从下标1一直到下标4,但是不包括下标4
numbers1 :=numbers[1:4]
//从下标0一直到下标3,但是不包括下标3
numbers2 :=numbers[:3]
//从下标3一直到结束
numbers3 :=numbers[3:]
切片截取例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package main
import "fmt"
//1、切片可以修改大小
//2、切片的拷贝不是单纯值的拷贝,一个切片指向了一个数组
//切片的声明1
var slice1 []int
//切片的声明2
var slice2 []int = make([]int,5)
var slice3 []int = make([]int,5,7)
func main(){
slice4 := make([]int,5)
slice5 := make([]int,5,7)
slice6 := make([]int,0)
fmt.Printf("len=%d,cap=%d,slice=%v\n",len(slice4),cap(slice4),slice4)
fmt.Printf("len=%d,cap=%d,slice=%v",len(slice5),cap(slice5),slice5)
if slice4 ==nil{
fmt.Printf("len=%d,cap=%d,slice=%v\n",len(slice4),cap(slice4),slice4)
}
//slice6 := make([]int,0)不为nil
if slice6 !=nil{
fmt.Printf("len=%d,cap=%d,slice=%v\n",len(slice6),cap(slice6),slice6)
}
//var slice1 []int为nil
if slice1 ==nil{
fmt.Printf("len=%d,cap=%d,slice=%v\n",len(slice1),cap(slice1),slice1)
}
sliceTest()
}
//截取
func sliceTest(){
numbers:= []int{1,2,3,4,5,6,7,8}
printSliceInfo(numbers)
numbers1 :=numbers[1:4]
printSliceInfo(numbers1)
numbers2 :=numbers[:3]
printSliceInfo(numbers2)
numbers3 :=numbers[3:]
printSliceInfo(numbers3)
}
//打印切片
func printSliceInfo(x []int){
fmt.Printf("len=%d,cap=%d,slice=%v\n",len(x),cap(x),x)
}
利用切片截取进行删除
1
2
3
4
5
6
7
8
9
10
11
//切片删除
//删除第一个元素
numbers = numbers[1:]
//删除最后一个
numbers = numbers[:len(numbers)-1]
//删除中间一个元素
a := int(len(numbers) / 2)
numbers = append(numbers[:a], numbers[a+1:]...)
切片与数组的拷贝对比
数组的拷贝是副本拷贝。对于副本的改变不会影响到
切片的拷贝很特殊,切片的副本仍然指向了相同的数组。所以,对于副本的修改会影响到相同的数组。
下面的例子说明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main
import "fmt"
func main() {
//数组是值类型
a := [4]int{1, 2, 3, 4}
//切片是引用类型
b := []int{100, 200, 300}
c := a
d := b
c[1] = 200
d[0] = 1
fmt.Println("a=", a, "c=", c)
//c[1 200 3 4] a[1 2 3 4]
fmt.Println("b=", b, "d=", d)
//d[1 200 300] b[1 200 300]
}
append添加元素
1
2
3
4
5
6
7
8
9
10
11
12
13
numbers := make([]int, 0, 20)
//append一个元素
numbers = append(numbers, 0)
//append多个元素
numbers = append(numbers, 1, 2, 3, 4, 5, 6, 7)
//append添加切片
s1 := []int{100, 200, 300, 400, 500, 600, 700}
numbers = append(numbers, s1...) //[0 1 2 3 4 5 6 7 100 200 300 400 500 600 700]
copy
毫无疑问,创建新的目标切片就会有新的指向的数组。数组的copy是对于不同的数组的值的拷贝
1
2
3
4
5
//创建目标切片
numbers1 := make([]int, len(numbers), cap(numbers)*2)
//将numbers的元素拷贝到numbers1中
count := copy(numbers1, numbers)
例子2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package main
import "fmt"
func main() {
fmt.Println("1、--------------")
//var numbers []int
numbers := make([]int, 0, 20)
//append一个元素
numbers = append(numbers, 0)
printSlice("numbers:", numbers) //[0]
//append多个元素
numbers = append(numbers, 1, 2, 3, 4, 5, 6, 7)
printSlice("numbers:", numbers) //[0 1 2 3 4 5 6 7]
//append添加切片
s1 := []int{100, 200, 300, 400, 500, 600, 700}
numbers = append(numbers, s1...) //[0 1 2 3 4 5 6 7 100 200 300 400 500 600 700]
printSlice("numbers:", numbers)
fmt.Println("2、--------------")
//切片删除
//删除第一个元素
numbers = numbers[1:]
printSlice("numbers:", numbers) //[ 1 2 3 4 5 6 7 100 200 300 400 500 600 700]
//删除最后一个
numbers = numbers[:len(numbers)-1]
printSlice("numbers:", numbers) //[ 1 2 3 4 5 6 7 100 200 300 400 500 600]
//删除中间一个元素
a := int(len(numbers) / 2)
fmt.Println("中间下标:", a)
numbers = append(numbers[:a], numbers[a+1:]...)
printSlice("numbers:", numbers) //[1 2 3 4 5 6 100 200 300 400 500 600]
fmt.Println("3、--------------")
//创建目标切片
numbers1 := make([]int, len(numbers), cap(numbers)*2)
//将numbers的元素拷贝到numbers1中
count := copy(numbers1, numbers)
fmt.Println("拷贝的个数:", count)
printSlice("numbers1:", numbers1)
//拷贝的两个切片是否有关联
numbers[0] = 99
numbers1[len(numbers1)-1] = 100
printSlice("numbers", numbers)
printSlice("numbers1", numbers1)
}
func printSlice(name string, x []int) {
fmt.Print(name, "\t")
fmt.Printf("地址:%p \t len=%d \t cap=%d \t value=%v \n", x, len(x), cap(x), x)
}
疯狂切片原理
理解了下面代码到底输出什么,就理解了切片的原理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main
import "fmt"
func f(s []string, level int) {
if level > 5 {
return
}
s = append(s, fmt.Sprint(level))
f(s, level+1)
fmt.Println("level:", level, "slice:", s)
}
func main() {
f(nil, 0)
}
输出结果:
1
2
3
4
5
6
level: 5 slice: [0 1 2 3 4 5]
level: 4 slice: [0 1 2 3 4]
level: 3 slice: [0 1 2 3]
level: 2 slice: [0 1 2]
level: 1 slice: [0 1]
level: 0 slice: [0]
参考资料:
https://dave.cheney.net/2018/07/12/slices-from-the-ground-up
本文链接:https://dreamerjonson.com/2018/11/20/golang-13-slice/
版权声明:本博客所有文章除特别声明外,均采用CC BY 4.0 CN协议许可协议。转载请注明出处!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。