第14讲 Go切片与Map
本讲基于视频实际讲解内容整理
一、切片(Slice)简介
老师在上一讲数组的基础上,引入了切片的概念。切片是Go语言中非常重要的数据结构,解决了数组长度固定的限制。
二、切片的定义
切片的声明方式与数组类似,但不需要指定长度:
Go
// 数组:需要指定长度
var arr [3]int
// 切片:不需要指定长度
var s []int
关键区别:数组声明时方括号内有数字(如
[3]int),切片声明时方括号内为空(如[]int)。
三、切片是引用类型
老师特别强调,切片与数组最大的区别在于:切片是引用类型。
切片的底层由三部分构成:
| 组成部分 | 说明 |
|---|---|
| 指针 | 指向底层数组的起始地址 |
| 长度(len) | 当前切片中元素的个数 |
| 容量(cap) | 从切片起始位置到底层数组末尾的元素个数 |
因为切片是引用类型,所以对切片的修改会影响到共享同一底层数组的其他切片。
四、append() 添加元素
使用内置函数 append() 向切片中添加元素:
Go
package main
import "fmt"
func main() {
var s []int
s = append(s, 1)
s = append(s, 2)
s = append(s, 3)
fmt.Println(s) // [1 2 3]
}
重要注意:
append()的返回值必须赋值回原变量。因为切片是引用类型,当容量不够时,Go会创建一个新的底层数组,此时原切片的指针不会自动更新,必须用返回值重新赋值。
Go
// ✅ 正确写法
s = append(s, 10)
// ❌ 错误写法(不会报错,但元素不会被添加)
append(s, 10)
老师强调:数组不支持
append(),只有切片才能使用append()。
五、切片删除元素
Go没有提供直接删除切片元素的内置函数,需要手动操作。删除元素的核心思路是:使用 copy() 函数将后面的元素向前移动。
Go
package main
import "fmt"
func main() {
s := []int{1, 2, 3, 4, 5}
// 删除下标为2的元素(值为3)
index := 2
// 将index之后的元素前移
copy(s[index:], s[index+1:])
// 去掉最后一个元素
s = s[:len(s)-1]
fmt.Println(s) // [1 2 4 5]
}
删除步骤:
- 用
copy()把要删除位置后面的元素全部前移一位 - 用切片截断去掉最后一个多余元素
六、Map(映射)
6.1 Map的定义
Map是Go中的键值对(key-value)数据结构,定义语法:
Go
// 定义一个key为string、value为int的Map
var m map[string]int
6.2 使用 make() 创建Map
Map是引用类型,声明后需要用 make() 函数分配内存才能使用:
Go
package main
import "fmt"
func main() {
// 使用make创建Map
m := make(map[string]int)
// 添加键值对
m["张三"] = 90
m["李四"] = 85
fmt.Println(m) // map[张三:90 李四:85]
fmt.Println(m["张三"]) // 90
}
如果只声明不
make(),直接赋值会报错(nil map不能写入)。
七、Map的类型约束
老师强调了Map的两条重要规则:
7.1 所有key类型必须一致
Go
// ✅ 正确:所有key都是string
m := make(map[string]int)
m["name"] = 1
m["age"] = 2
// ❌ 错误:key类型不一致
m := make(map[string]int)
m["name"] = 1
m[100] = 2 // 编译错误!key必须是string
7.2 所有value类型必须一致
Go
// ✅ 正确:所有value都是int
m := make(map[string]int)
m["a"] = 1
m["b"] = 2
// ❌ 错误:value类型不一致
m["a"] = 1
m["b"] = "hello" // 编译错误!value必须是int
7.3 key和value类型可以不同
key的类型和value的类型不需要相同,只要各自内部一致即可:
Go
// key是string,value是int —— 完全合法
m := make(map[string]int)
// key是int,value是string —— 也合法
m2 := make(map[int]string)
7.4 key类型必须支持 == 比较
Map的key必须支持 == 运算符进行比较,因为Map需要通过key来查找元素。
| key类型 | 是否可用 |
|---|---|
| string | ✅ |
| int/float | ✅(但不建议用float) |
| bool | ✅ |
| 数组 | ✅ |
| 指针 | ✅ |
| 切片 | ❌ 不支持比较 |
| Map | ❌ 不支持比较 |
| 函数 | ❌ 不支持比较 |
老师提醒:浮点数理论上可以做key(因为支持
==),但不建议使用,因为浮点数精度问题可能导致查找失败。
八、本讲小结
| 知识点 | 要点 |
|---|---|
| 切片定义 | []T,不指定长度 |
| 引用类型 | 切片由指针、长度、容量三部分构成 |
| append() | 添加元素,必须赋值回原变量 |
| append() 限制 | 只有切片可用,数组不可用 |
| 删除元素 | 使用 copy() 前移元素 + 截断 |
| Map定义 | map[keyType]valueType |
| Map创建 | 使用 make() 分配内存 |
| key约束 | 所有key类型一致,必须支持 == |
| value约束 | 所有value类型一致 |
| key/value | 两者类型可以不同 |
九、课后练习
- 声明一个
[]string切片,用append()添加3个名字,打印结果 - 尝试对数组使用
append(),观察编译错误信息 - 创建一个
map[string]int,存储5个同学的名字和成绩,遍历打印 - 尝试创建
map[int]string,观察key和value类型不同时是否合法 - 尝试用float64做Map的key,思考为什么老师说不建议这样做