06-slice 和 map

数组

数组长度固定,不建议用

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
package main
import "fmt"

//不建议使用,可以使用动态数组
func printArray (array [4]int){
//值拷贝
fmt.Println("---------------输出函数--------------")
for i := 0; i < len(array); i++ {
fmt.Println("array2_value = ", array[i])
}

//如果要对数组的值进行修改,下面这种传参是改不了的
// array[0] = 10000
}
func main () {
// 固定长度数组
var array1 [10]int
for i := 0; i < len(array1); i++ {
fmt.Println("array1_value = ", array1[i])
}
array2 := [10]int{1, 2, 4, 5}
array3 := [4]int{1, 2, 4, 5}
for index, value := range array2 {
fmt.Println("array2_index = ", index, "array2_value = ", value)
}

printArray(array3)

// 打印数组类型
fmt.Printf("array1 type : %T\n", array1)
fmt.Printf("array2 type : %T\n", array2)
fmt.Printf("array3 type : %T\n", array3)
}

slice\切片\动态数组

Go 语言切片是对数组的抽象。

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

定义切片四种方式

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
package main

import (
"fmt"

)
func main() {

// 声明slice1是一个切片,并且初始化,长度是3,默认值是1, 2, 3。
// [] 表示是切片类型,{1,2,3} 初始化值依次是 1,2,3 其中 cap=len=3
slice1 := []int{1, 2, 3}

// 声明slice2是一个切片,但是没有分配空间,len = 0,value = []
var slice2 []int
// 可以通过make来开辟几个空间,这时候len = 3,value = [0, 0, 0]
slice2 = make([]int, 3)

// 声明slice3是一个切片,通过make来开辟3空间,这时候len = 3,value = [0, 0, 0]
var slice3 []int = make([]int, 3)

// 或者简写为以下。通过:=推测出他是一个切片
slice4 := make([] int, 3)

// 利用数组初始化切片,是数组 arr 的引用
// 语法:s := arr[startIndex:endIndex]
// 将 arr 中从下标 startIndex 到 endIndex-1 下的元素创建为一个新的切片
// 缺省endIndex时将表示一直到arr的最后一个元素
// 缺省startIndex时将表示从arr的第一个元素开始
s := arr[:]

fmt.Printf("len = %d , value = %v\n", len(slice1), slice1)

// 判断一个切片是否为空
if slice1 == nil {
fmt.Println("slice1 is null!")
} else {
fmt.Println("slice2 is not null!!")
}
}

len()cap() 函数

切片是可索引的,并且可以由 len() 方法获取长度。

切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。

以下为具体实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main


import "fmt"


func main() {
var numbers = make([]int,3,5)
printSlice(numbers)
}


func printSlice(x []int){
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

以上实例运行输出结果为:

1
len=3 cap=5 slice=[0 0 0]

空(nil)切片

一个切片在未初始化之前默认为 nil,长度为 0,实例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main


import "fmt"


func main() {
var numbers []int
printSlice(numbers)

if(numbers == nil){
fmt.Printf("切片是空的")
}
}


func printSlice(x []int){
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

以上实例运行输出结果为:

1
2
len=0 cap=0 slice=[]
切片是空的

切片截取

可以通过设置下限及上限来设置截取切片 [lower-bound: upper-bound],实例如下:

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
package main


import "fmt"


func main() {
/* 创建切片 */
numbers := []int{0,1,2,3,4,5,6,7,8}
printSlice(numbers)


/* 打印原始切片 */
fmt.Println("numbers ==", numbers)


/* 打印子切片从索引1(包含) 到索引4(不包含)*/
fmt.Println("numbers[1:4] ==", numbers[1:4])


/* 默认下限为 0*/
fmt.Println("numbers[:3] ==", numbers[:3])


/* 默认上限为 len(s)*/
fmt.Println("numbers[4:] ==", numbers[4:])


numbers1 := make([]int,0,5)
printSlice(numbers1)


/* 打印子切片从索引 0(包含) 到索引 2(不包含) */
number2 := numbers[:2]
printSlice(number2)


/* 打印子切片从索引 2(包含) 到索引 5(不包含) */
number3 := numbers[2:5]
printSlice(number3)
}


func printSlice(x []int){
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

执行以上代码输出结果为:

1
2
3
4
5
6
7
8
len=9 cap=9 slice=[0 1 2 3 4 5 6 7 8]
numbers == [0 1 2 3 4 5 6 7 8]
numbers[1:4] == [1 2 3]
numbers[:3] == [0 1 2]
numbers[4:] == [4 5 6 7 8]
len=0 cap=5 slice=[]
len=2 cap=9 slice=[0 1]
len=3 cap=7 slice=[2 3 4]

深拷贝 copy()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import "fmt"

func main () {
// slice切片
s := [] int{1, 2, 3, 4}
s1 := s[0:2] //s1是s中的索引在[0, 2)区间的元素,和python类似
fmt.Println("s1 = ", s1)

s2 := s[1:] //s1是s中的索引在[1, len(s))区间的元素,和python类似
fmt.Println("s2 = ", s2)

//如若修改s1里面的元素,s也会随之改变,因为这种切片相当于指针指向了s,所以改s1值,s和s1会一起发生改变(浅拷贝)
s1[0] = 20000
fmt.Println("s = ", s)

// go提供了copy函数,切片的时候只将值复制过来,(深拷贝)
s3 := make([] int, 3) //[0, 0, 0]

// 将s2的值依次拷贝到s3中
copy(s3, s2)
fmt.Println("s3 = ", s3)
}

追加 append()

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
package main


import "fmt"


func main() {
var numbers []int
printSlice(numbers)

/* 允许追加空切片 */
numbers = append(numbers, 0)
printSlice(numbers)


/* 向切片添加一个元素 */
numbers = append(numbers, 1)
printSlice(numbers)


/* 同时添加多个元素 */
numbers = append(numbers, 2,3,4)
printSlice(numbers)
}


func printSlice(x []int){
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

以上代码执行输出结果为:

1
2
3
4
len=0 cap=0 slice=[]
len=1 cap=1 slice=[0]
len=2 cap=2 slice=[0 1]
len=5 cap=6 slice=[0 1 2 3 4]

map

map 和 slice 类似,只不过是数据结构不同,下面是 map 的一些声明方式。

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
package main
import (
"fmt"
)

func main() {
//第一种声明
var test1 map[string]string
//在使用map前,需要先make,make的作用就是给map分配数据空间
test1 = make(map[string]string, 10)
test1["one"] = "php"
test1["two"] = "golang"
test1["three"] = "java"
fmt.Println(test1) //map[two:golang three:java one:php]

//第二种声明
test2 := make(map[string]string)
test2["one"] = "php"
test2["two"] = "golang"
test2["three"] = "java"
fmt.Println(test2) //map[one:php two:golang three:java]

//第三种声明
test3 := map[string]string{
"one" : "php",
"two" : "golang",
"three" : "java",
}
fmt.Println(test3) //map[one:php two:golang three:java]


language := make(map[string]map[string]string)
language["php"] = make(map[string]string, 2)
language["php"]["id"] = "1"
language["php"]["desc"] = "php是世界上最美的语言"
language["golang"] = make(map[string]string, 2)
language["golang"]["id"] = "2"
language["golang"]["desc"] = "golang抗并发非常good"

fmt.Println(language) //map[php:map[id:1 desc:php是世界上最美的语言] golang:map[id:2 desc:golang抗并发非常good]]


//增删改查
// val, key := language["php"] //查找是否有php这个子元素
// if key {
// fmt.Printf("%v", val)
// } else {
// fmt.Printf("no");
// }

//language["php"]["id"] = "3" //修改了php子元素的id值
//language["php"]["nickname"] = "啪啪啪" //增加php元素里的nickname值
//delete(language, "php") //删除了php子元素
fmt.Println(language)


// 遍历
for key, value := range language {
fmt.Println("key = ", key, ", value = ", value)
}
}

06-slice 和 map
https://flepeng.github.io/021-Go-01-course-06-slice-和-map/
作者
Lepeng
发布于
2024年11月1日
许可协议