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

image.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章