Golang 教程6——切片、映射
注意,该文档只适合有编程基础的同学,这里的go教程只给出有区别的知识点
1、数组有特定的用处, 但是有些呆板(数组的长度固定不变), 所以在Go语言的代码里不是特别常见。相对的,切片随处可见,切片是一种建立在数组类型之上的抽象,它构建在数组之上并且提供强大的能力和便捷。
2、切片(slice)是对数组一个连续片段的引用, 所以切片是一个引用类型。这个片段可以是整个数组,或者是由起始和终止索引标识的一些项的子集。
切片有3个字段的数据结构: 一个是指向底层数组的指针, 一个是数组的长度, 一个是切片的容量。
1.1 main文件
package main
import (
"fmt"
)
func main() {
var arr = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// 1、定义方式1: 切片定义在数组之上
// 定义一个切片,名字为slice,类型为int,[]动态变化的数组长度不写, arr是原数组
// [2:5]切片, 2是起始位置,5是结束位置(不包括5) ->[2, 5)
slice := arr[2:5]
// 打印切片
fmt.Println("slice:", slice)
// 打印切片长度
fmt.Println(len(slice))
// 打印切片容量: 容量可以动态变化
fmt.Println(cap(slice))
//通过切片对数据中的元素进行改变
slice[0] = 100
slice[1] = 200
fmt.Println(arr)
fmt.Println(slice)
//2、定义方式2:通过内置函数make创建切片 make(切片的类型,切片长度, 切片的容量)
//make会在底层创建一个数组,但是这个数组在外界是不可见的。
slice1 := make([]int, 5, 10)
slice1[0] = 1
slice1[1] = 2
fmt.Println(slice1)
//3、定义方式3:定义一个切片, 直接就指定具体数组,使用原理类似make方式
slice2 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
fmt.Println("slice2: ", slice2)
fmt.Println("---------------------------------------------------------")
}
/*
切片在定义之后不能直接使用,需要让其引用到一个数组,或者make一个空间供切片使用
切片的使用不能越界
简写方式
1) var slice = arr[0: end] --> var slice = arr[: end]
2) var slice = arr[start:len(arr)] --> var slice = arr[start:]
3) var slice = arr[0:len(arr)] --> var slice = arr[:]
切片后可以继续切片
var slice1 [6]int = [6]int{1, 2, 3, 4, 5, 6}
var slice2 = slice1[2:5] 注意,下标都是从0开始的
*/
1.2 输出结果
(base) PS E:\Goproject\src\gocode\testproject01> go run ./main/main.go
[3 4 5]
3
8
[1 2 100 200 5 6 7 8 9 10]
[100 200 5]
[1 2 0 0 0]
slice2: [1 2 3 4 5 6 7 8 9 10]
1.3 切片的操作
func main () {
slice2 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
//4、切片的遍历
for i, val := range slice2 {
fmt.Println(i, val)
}
// 切片增加元素
// 底层原理:
// 底层追加元素的时候,会创建一个新的底层数组,然后把原来的数组拷贝到新的数组中,
// 然后把新的数组赋值给slice3,然后把新的slice3返回
slice3 := append(slice2, 11, 12, 13, 14, 15)
fmt.Println(slice3)
// 往往我们在使用追加的时候其实想要做的效果是给slice追加:
slice2 = append(slice2, 11, 12, 13, 14, 15)
//可以将切片追加给切片
slice4 := append(slice2, slice3...)
fmt.Println("slice4:", slice4)
//切片删除元素 s = append(s[:indexToDelete], s[indexToDelete+1:]...)
slice5 := append(slice2[:3], slice2[5:]...) //删除下表为3、4的元素
fmt.Println("slice5:", slice5)
//切片拷贝
var newArr []int = make([]int, 20)
copy(newArr, slice2)
fmt.Println("newArr:", newArr)
}
1.4 输出结果
(base) PS E:\Goproject\src\gocode\testproject01> go run ./main/main.go
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]
slice4: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]
slice5: [1 2 3 6 7 8 9 10 11 12 13 14 15]
newArr: [1 2 3 6 7 8 9 10 11 12 13 14 15 14 15 0 0 0 0 0]
2. 映射
2.1 映射的定义
func main() {
//方式1: 定义map变量:
var m map[int] string
// 只声明map变量,没有初始化,程序不会分配空间,所以为nil
// 必须通过make函数进行初始化, 才会分配空间
fmt.Println(m)
//key的值不能重复,否则会覆盖, value可以重复
// m[key] = value
m = make(map[int] string, 10)
m[1] = "2009年"
m[1] = "2029年"
m[2] = "2019年"
m[3] = "2019年"
fmt.Println("方式1:", m)
//方式2: 定义map变量:
m2 := make(map[int] string)
m2[1] = "2009年"
m2[1] = "2029年"
m2[2] = "2019年"
m2[3] = "2019年"
fmt.Println("方式2:", m2)
//方式3: 直接定义map变量:
m3 := map[int] string{
1: "2009年",
2: "2019年",
3: "2019年",
}
fmt.Println("方式3:", m3)
}
2.2 输出结果
(base) PS E:\Goproject\src\gocode\testproject01> go run ./main/main.go
map[]
方式1: map[1:2029年 2:2019年 3:2019年]
方式2: map[1:2029年 2:2019年 3:2019年]
方式3: map[1:2009年 2:2019年 3:2019年]
2.3 映射的基本操作
func main() {
m3 := map[int] string{
1: "2009年",
2: "2019年",
3: "2019年",
}
fmt.Println(m3)
//1、删除操作
delete(m3, 2)
fmt.Println("删除key为2之后:", m3)
//2、清空操作,没有专门的办法清空,直接重新声明一个map即可
// m3 = make(map[int] string, 10)
// fmt.Println(m3)
//3、查找, value 表示值, flag 表示是否存在
value, flag := m3[2]
fmt.Println("当前map", m3)
fmt.Println("查找key为2的value:", value, flag)
//4、获取map的长度
fmt.Println("当前map的长度:", len(m3))
//5、遍历map
for k, v := range m3 {
fmt.Println("key:", k, "value:", v)
}
}
2.4 输出结果
(base) PS E:\Goproject\src\gocode\testproject01> go run ./main/main.go
map[1:2009年 2:2019年 3:2019年]
删除key为2之后: map[1:2009年 3:2019年]
当前map map[1:2009年 3:2019年]
查找key为2的value: false
当前map的长度: 2
key: 3 value: 2019年
key: 1 value: 2009年