go切片截取不复制数据,仅修改header三字段,新旧切片共享底层数组,故修改重叠索引会影响原数组;越界直接panic而非返回nil;max参数限定新切片cap上限,决定append是否扩容。

Go 的 slice 截取不复制数据,只改 header;越界直接 panic,不是返回空或 nil。
slice[low:high] 为什么有时改了原数组?
因为截取只是调整指针、len 和 cap,新旧 slice 共享同一底层数组。只要修改的是重叠索引位置的元素,就会相互影响。
-
s := []int{0,1,2,3,4}→t := s[1:3]后,t[0] = 99会让s变成[0,99,2,3,4] - 这种共享在函数传参时尤其隐蔽:传入
func f(s []int)再做s[0] = x,调用方看到的原始切片也会变 - 若想彻底隔离,必须显式复制:
copy(dst, src)或append([]int(nil), src...)
slice[low:high:max] 的 max 参数到底控制什么?
max 不是“最大允许下标”,而是新切片的 cap 上限,即 cap(new) == max - low。它限制后续 append 是否触发扩容。
-
s := make([]int, 5, 10)→t := s[1:4:6]:t 的len=3,cap=5(6−1),append(t, 0)仍在容量内,复用原底层数组 - 若写成
s[1:4:4],则cap=3,第一次append就会分配新数组,切断共享 -
max超出原底层数组长度(比如原数组长 10,max=11)会 panic:slice bounds out of range
字符串截取 s[start:end] 为什么中文会乱码?
Go 字符串底层是字节序列,s[2:5] 按字节切,UTF-8 编码的中文占 3 字节,emoji 可能占 4 字节——直接切可能截断中间,导致 invalid UTF-8。
- 错误示范:
s := "你好a"; s[0:4]→ 前 4 字节是"你好"的前 3 字节 +"a"的第 1 字节,解码失败 - 正确做法:先转
[]rune,再切,再转回string:rs := []rune(s); string(rs[0:2]) - 注意:空字符串或
nil不能直接切,len(s)返回字节数,不是字符数;判断字符长度要用len([]rune(s))
真正容易被忽略的是:cap 不是“预留空间”,而是“从当前起始位置到底层数组末尾还能塞多少个元素”;这个值决定了 append 是就地写还是换新数组——而换新数组的时机,恰恰是内存泄漏或意外共享的分水岭。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











