其他
在 Go 中处理 slice、map、array…
适用于使用 Go slices、maps 或 arrays,并需要选择数据结构、声明空切片、实现 set 或在边界复制数据的场景。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 48/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 55/100 ×0.15
适用场景
在 Go 中处理 slice、map、a通用
解决思路
- 需要决定 nil 还是空切片、复制切片、管理切片容量或别名时,阅读 references/SLICES.md。
- 选择数据结构:有序集合且大小在编译时固定时使用 Array [N]T。
- 选择数据结构:动态大小使用 Slice []T。
- 选择 Slice 时:知道近似大小时使用 make([]T, 0, capacity)。
- 选择 Slice 时:大小未知或需要 JSON nil 安全时使用 var s []T(nil)。
- 键值查找使用 Map map[K]V。
- 选择 Map 时:知道近似大小时使用 make(map[K]V, capacity)。
- 需要集合时使用 map[T]struct{}(零大小值)。
- 需要传给函数时,如果调用方可能修改它,在边界复制。
- 使用 append 时始终赋值结果:x = append(x, 4, 5, 6),因为底层数组可能改变。
- 将切片附加到切片:x = append(x, y...),注意 ...。
- 构建二维切片时,如需内层切片能独立增长或收缩:picture := make([][]uint8, YSize); for i := range picture { picture[i] = make([]uint8, XSize) }。
- 构建二维切片时,如大小固定且追求单次分配更高效:picture := make([][]uint8, YSize); pixels := make([]uint8, XSize*YSize); for i := range picture { picture[i], pixels = pixels[:XSize], pixels[XSize:] }。
- 声明空切片时优先 nil slice:var t []string。
- 避免声明非 nil 但零长度切片:t := []string{};两者 len 和 cap 都为 0,但 nil slice 是首选风格。
- JSON 例外:nil slice 编码为 null,[]string{} 编码为 [];需要 JSON 数组时使用非 nil 切片。
- 设计接口时避免区分 nil 和非 nil 零长度切片。
- 用 map 实现 set 时使用 map[T]struct{};空 struct 不占存储,并明确成员意图。
- 示例:attended := map[string]struct{}{"Ann": {}, "Joe": {}};检查成员:if _, ok := attended[person]; ok { ... }。
- 仅当布尔 map 值承载独立于存在性的含义时,才使用布尔值 map。
- 从其他包复制 struct 时要小心;如果类型的方法在指针类型 *T 上,复制值可能导致别名 bug。
- 通用规则:如果类型 T 的方法关联到 *T,不要复制 T 的值;适用于 bytes.Buffer、sync.Mutex、sync.WaitGroup 以及包含它们的类型。
- 不要复制 mutex:var mu sync.Mutex; mu2 := mu 几乎总是 bug。
- 通过指针传递带 mutex 的类型:func increment(sc *SafeCounter) { sc.mu.Lock(); sc.count++; sc.mu.Unlock() }。
- Quick Reference:Slices 始终赋值 append 结果;优先 nil slice 而不是 []T{}。
- Quick Reference:Sets 使用 map[T]struct{} 表示仅做成员判断的集合。
- Quick Reference:Copying 如果方法在 *T 上不要复制 T;警惕别名。
- 需要 API 边界防御性复制以防止修改时,参见 go-defensive。
- 需要为已知工作负载预分配切片或 map 容量时,参见 go-performance。
- 需要在 slice、map 或 channel 上使用 range 循环时,参见 go-control-flow。
- 需要在 new、make、var 和复合字面量之间选择声明风格时,参见 go-declarations。
适用边界 · 注意事项
- 不适用于并发访问数据结构的场景(mutex、atomic 操作),应参见 go-concurrency。
- 不适用于在 API 边界做防御性复制的场景,应参见 go-defensive。
- 不适用于为了性能预分配容量的场景,应参见 go-performance。