Go06-数组、切片与 Map

发布时间:2026/7/16 23:01:27
Go06-数组、切片与 Map 第5章数组、切片与 Map5.1 数组数组是固定长度的同类型元素序列。声明与初始化// 声明数组vararr1[5]int// [0 0 0 0 0]// 初始化arr2:[5]int{1,2,3,4,5}// 自动计算长度arr3:[...]int{1,2,3,4,5}// 指定索引初始化arr4:[5]int{1:10,3:30}// [0 10 0 30 0]// 多维数组matrix:[2][3]int{{1,2,3},{4,5,6},}数组操作arr:[5]int{1,2,3,4,5}// 访问元素fmt.Println(arr[0])// 1// 修改元素arr[0]10// 遍历fori,v:rangearr{fmt.Printf(索引: %d, 值: %d\n,i,v)}// 数组长度fmt.Println(len(arr))// 5数组特性// 数组是值类型赋值会复制a:[3]int{1,2,3}b:a b[0]10fmt.Println(a)// [1 2 3] - a 不受影响fmt.Println(b)// [10 2 3]// 比较相同类型数组可以比较a1:[3]int{1,2,3}a2:[3]int{1,2,3}fmt.Println(a1a2)// true5.2 切片切片是动态长度的序列是对底层数组的抽象。创建切片// 使用字面量s1:[]int{1,2,3,4,5}// 使用 make 创建s2:make([]int,5)// 长度为5容量为5s3:make([]int,0,10)// 长度为0容量为10// 从数组/切片创建arr:[5]int{1,2,3,4,5}s4:arr[1:3]// [2 3]s5:arr[:3]// [1 2 3]s6:arr[2:]// [3 4 5]s7:arr[:]// [1 2 3 4 5]切片操作s:[]int{1,2,3,4,5}// 添加元素sappend(s,6)// [1 2 3 4 5 6]sappend(s,7,8,9)// [1 2 3 4 5 6 7 8 9]// 复制切片dst:make([]int,len(s))copy(dst,s)// 删除元素索引2sappend(s[:2],s[3:]...)// 插入元素在索引2处插入10sappend(s[:21],s[2:]...)s[2]10// 切片表达式s[]int{1,2,3,4,5}s2:s[1:3]// [2 3]s3:s[:3]// [1 2 3]s4:s[2:]// [3 4 5]切片长度与容量s:make([]int,5,10)fmt.Println(长度:,len(s))// 5fmt.Println(容量:,cap(s))// 10// 追加元素时容量不足会触发扩容sappend(s,1,2,3)fmt.Println(长度:,len(s))// 8fmt.Println(容量:,cap(s))// 10// 继续追加容量翻倍sappend(s,4,5,6)fmt.Println(长度:,len(s))// 11fmt.Println(容量:,cap(s))// 20切片是引用类型// 切片共享底层数组s1:[]int{1,2,3,4,5}s2:s1[1:3]s2[0]20fmt.Println(s1)// [1 20 3 4 5] - s1 也受影响// 使用 copy 避免共享s3:make([]int,len(s2))copy(s3,s2)s3[0]200fmt.Println(s2)// [20 3] - s2 不受影响5.3 MapMap 是键值对的无序集合。创建 Map// 使用字面量m1:map[string]int{张三:25,李四:30,}// 使用 make 创建m2:make(map[string]int)// 添加元素m2[王五]35// 删除元素delete(m2,王五)// 检查键是否存在age,ok:m2[张三]ifok{fmt.Println(年龄:,age)}// 获取长度fmt.Println(len(m2))Map 遍历m:map[string]int{张三:25,李四:30,王五:35,}// 遍历顺序随机forname,age:rangem{fmt.Printf(%s: %d岁\n,name,age)}// 只遍历键forname:rangem{fmt.Println(name)}// 只遍历值for_,age:rangem{fmt.Println(age)}Map 作为集合// 使用空结构体作为值不占内存set:map[string]struct{}{apple:{},banana:{},cherry:{},}// 添加元素set[date]struct{}{}// 检查元素是否存在if_,exists:set[apple];exists{fmt.Println(apple 存在)}// 删除元素delete(set,banana)Map 作为计数器// 统计字符出现次数funccountChars(sstring)map[rune]int{count:make(map[rune]int)for_,ch:ranges{count[ch]}returncount}result:countChars(hello world)forch,count:rangeresult{fmt.Printf(%c: %d\n,ch,count)}5.4 切片与 Map 的最佳实践预分配内存// 不推荐频繁扩容vars[]intfori:0;i1000;i{sappend(s,i)}// 推荐预分配容量s:make([]int,0,1000)fori:0;i1000;i{sappend(s,i)}// Map 同理m:make(map[string]int,1000)安全地访问 Map// 使用 ok 模式检查键是否存在funcgetAge(mmap[string]int,namestring)(int,bool){age,ok:m[name]returnage,ok}// 使用 sync.Map 并发安全见并发章节5.5 练习实现一个函数合并两个切片并去重实现一个简单的 LRU 缓存使用切片和 map编写程序统计一段文本中每个单词的出现次数实现一个函数将 map 的键和值互换5.6 下一章下一章我们将学习 Go 语言的结构体与接口。