Go语言-初学者日记(二):数组、切片与 map,一篇彻底弄懂集合类型!
集合类型是 Go 的核心组成部分。本篇带你用图文和例子深入理解数组、切片、map 的使用方式与区别,避免踩坑,写出更地道的 Go 代码!
🧮 一、数组(Array):定长集合类型
var arr [3]int = [3]int{1, 2, 3}
数组的长度是类型的一部分,不能动态改变。
也可以用 ...
自动推导长度:
arr := [...]string{"Go", "Python", "Java"}
访问元素和遍历数组:
fmt.Println(arr[0])
for i, v := range arr {
fmt.Println(i, v)
}
📌 注意:数组是值类型,赋值或传参会复制整个数组,不是引用!
arr1 := [3]int{1, 2, 3}
arr2 := arr1
arr2[0] = 99
fmt.Println(arr1) // [1 2 3]
fmt.Println(arr2) // [99 2 3]
🧠 这就像是复印机,不是快递点。
🪓 二、切片(Slice):数组的升级版
切片是 Go 中使用最频繁的集合类型:
nums := []int{10, 20, 30}
nums = append(nums, 40) // 动态增长
从数组切出切片:
slice := arr[1:3] // 包含下标 1,不包含 3
查看长度和容量:
fmt.Println(len(slice)) // 元素数量
fmt.Println(cap(slice)) // 底层数组容量(从起点到底)
📌 切片是引用类型,赋值给另一个变量,修改会影响原切片:
s1 := []int{1, 2, 3}
s2 := s1
s2[0] = 100
fmt.Println(s1) // [100 2 3]
💣 小心“多处引用共用内存”的副作用!写函数时如果要避免修改,记得手动 copy:
copied := append([]int(nil), s1...)
🗺️ 三、map(映射):键值对集合
m := map[string]int{"Alice": 90, "Bob": 85}
fmt.Println(m["Alice"])
动态添加/更新/删除:
m["Charlie"] = 78 // 添加
m["Bob"] = 88 // 更新
delete(m, "Alice") // 删除
安全读取建议加判断:
score, ok := m["Alice"]
if ok {
fmt.Println("存在:", score)
} else {
fmt.Println("不存在")
}
📌 map 也是引用类型,多个变量指向同一个底层数据:
m1 := map[string]int{"Tom": 60}
m2 := m1
m2["Tom"] = 100
fmt.Println(m1) // map[Tom:100]
🧠 遍历 map 是无序的:
for name, score := range m {
fmt.Println(name, score)
}
🔍 对比总结
类型 | 是否引用类型 | 是否定长 | 是否支持动态增删 | 是否有顺序 | 适用场景 |
---|---|---|---|---|---|
数组 | 否(值类型) | ✅ | ❌ | ✅(固定) | 定长固定结构 |
切片 | ✅(引用类型) | ❌ | ✅ | ✅(顺序) | 常用集合操作 |
map | ✅(引用类型) | ❌ | ✅ | ❌(无序) | 映射类结构 |
🧠 总结
- ✅ 数组适合处理固定长度、静态配置数据
- ✅ 切片是 Go 最常用集合,支持 append、切片、cap 计算等
- ✅ map 是键值对利器,适合处理查找、计数、映射等逻辑
📚 推荐练习:
- 实现一个成绩管理系统,支持添加、查询、修改、删除学生成绩(用 map 实现)
- 实现一个切片去重函数(使用 map 辅助)
- 实现一个数组翻转函数,尝试值类型的复制特性
📌 下一篇预告:Go语言-初学者日记(三):函数与方法,走进 Go 的函数世界!