数组传参改不了原值,切片能改但可能意外影响别人;大数组应传指针或转切片;截取切片需防重叠;用copy隔离数据;len是当前长度,cap是容量上限;预估最大量设cap可避免频繁扩容;数组可比较、作map键,切片不可。

数组传参改不了原值,切片能改但可能意外影响别人
Go里arr [3]int传进函数后,函数里改的是副本,外面完全没变;而s []int传进去,改的是底层数组,原切片能看到变化——但危险在于:如果多个切片共享同一底层数组,一个append或赋值可能悄悄改掉另一个的元素。
- 大数组别直接传参,要么传
*[1024]byte指针,要么转成切片再传 - 截取切片时注意重叠:
a := arr[1:3]和b := arr[2:4]共用arr[2],改a[1]等于改b[0] - 需要隔离数据?用
copy(dst, src)新建独立切片,别依赖make([]T, len(src))后直接赋值
len和cap不是一回事,扩容时机全看cap够不够
len(s)是你现在能读写的元素个数,cap(s)是“还能往里塞多少而不换底层数组”。很多bug就出在以为len == cap,结果append后返回的新切片指向了新地址,老变量还指着旧内存。
-
s := make([]int, 0, 5):长度0、容量5,第一次append(s, 1)不扩容,底层数组还是那块 -
s := []int{1,2,3}:长度3、容量也是3,再append必然扩容,底层数组大概率换地方 - 频繁追加?预估最大量设好
cap,比如日志缓冲make([]byte, 0, 4096),省掉多次复制
初始化写法决定底层是否复用,零值行为也完全不同
数组零值是[3]int{0,0,0},切片零值是nil。这直接影响if s == nil判断和append行为——对nil切片append是安全的,但对nil数组?压根不能nil数组,它必须有长度。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
-
var s []int→s是nil,len(s)==0且cap(s)==0,可直接append -
var a [3]int→a是[3]int{0,0,0},不能append,也不能nil比较 -
s := []int(nil)和s := []int{}都合法,但前者cap==0,后者cap通常为小整数(如2),影响首次扩容策略
什么时候非用数组不可?固定大小+可比较+当map键
切片不能做map的键,也不能用==直接比较;数组可以。典型场景:SHA256哈希值[32]byte、RGB颜色[3]uint8、矩阵行[4]float64。
- 想存一组固定ID?用
[16]byte而不是[]byte,既节省内存又支持map[[16]byte]string - 需要
==比相等?只有数组能直接比,切片得用bytes.Equal或循环 - 性能敏感且长度确定?比如网络包头解析,
[12]byte比[]byte少一次指针解引用
最常被忽略的一点:切片的cap不是摆设,它是你控制内存分配节奏的开关。很多人只盯着len,结果在高并发写日志时,每个请求都触发append扩容,底层数组反复复制——问题不在append本身,而在初始化时没给够cap。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










