Golang切片(Slice)入门_动态数组的创建与基本操作

1次阅读

切片是包含lencap和底层数组指针结构体,声明为[]t;数组是固定长度[n]t,二者类型不兼容。var s []intnil切片,var a [3]int为长度3的数组,a[:]可转为切片。

Golang切片(Slice)入门_动态数组的创建与基本操作

怎么声明一个切片,和数组有什么本质区别

切片不是数组的别名,而是包含 lencap 和指向底层数组的指针的结构体。声明时用 []T(没数字),而数组是 [N]T(有固定数字)。

  • var s []int 声明了一个 nil 切片,len(s)cap(s) 都是 0,但 s == nil 成立
  • var a [3]int 是长度为 3 的数组,占固定内存,不能直接传给期望 []int 的函数
  • 把数组转成切片要用 a[:],不是 a;传参时常见错误是把 [3]int 当作 []int 直接传,会编译报错:cannot use a (type [3]int) as type []int in argument

make 创建切片时,len 和 cap 参数怎么选

make([]T, len, cap) 中,len 是初始长度(可访问元素个数),cap 是底层数组总容量(决定后续 append 是否触发扩容)。

  • 如果只写 make([]int, 5),等价于 make([]int, 5, 5)cap 默认等于 len
  • 如果预估后续要追加很多元素,比如最终大概要 100 个,建议写 make([]int, 0, 100):避免多次 realloc 和复制,提升性能
  • cap 小于 len 会编译失败,这是语法错误,不是运行时 panic
  • cap 超过底层数组实际大小也没问题——因为 make 自己分配内存,你只是在定义逻辑上限

append 导致切片“意外共享”数据怎么办

append 在容量足够时不分配新内存,直接复用底层数组;如果多个切片共用同一底层数组,改一个可能影响另一个。

  • 常见现象:循环中反复 append 同一个切片,结果所有子切片内容“同步变化”
  • 根本原因:没有做深拷贝,比如 newSlice := oldSlice[:] 还是共享底层数组
  • 安全做法是显式复制:newSlice := append([]int(nil), oldSlice...)newSlice := make([]int, len(oldSlice)); copy(newSlice, oldSlice)
  • 注意 append([]int{}, s...) 看似简洁,但每次调用都新建底层数组,适合小数据;大数据量下 copy 更可控

切片截取越界 panic 怎么快速定位

panic 错误信息是:panic: runtime Error: slice bounds out of range [:n] with Length m,其中 n 是你请求的结束索引,m 是当前长度。

立即学习go语言免费学习笔记(深入)”;

  • 截取写法 s[i:j:k] 要同时满足:0 ≤ i ≤ j ≤ k ≤ cap(s);漏掉 k 时默认是 cap(s)
  • 容易踩坑的是用 s[i:] 时,以为 i 超过 len(s) 会返回空切片,其实只要 i > len(s) 就 panic(哪怕 i ≤ cap(s)
  • 调试建议:在截取前加一行 if i > len(s) { panic("index out of len") },比靠 panic 更早暴露逻辑错误
  • len(s)cap(s) 不相等时,尤其要注意 s[:]s[0:len(s)] 行为一致,但 s[0:cap(s)] 可能越界

切片的“动态”不体现在语法上,而在于你对 len/cap 关系的理解是否准确;多数 bug 都藏在扩容时机和底层数组复用这两个点里。

text=ZqhQzanResources