Go中字符串不可变、切片共享底层数组、map需make初始化且非并发安全;字符串用len()得字节长、utf8.RuneCountInString()得字符数;切片append后须接收返回值;map判键存在用v, ok := m[k]。
Go语言中字符串、切片和map是日常开发最频繁使用的三种类型,它们不可互换,但各有清晰的语义和操作边界。掌握其核心方法与常见陷阱,比死记API更重要。
Go中字符串底层是只读字节序列(string本质是结构体:{data *byte, len int}),因此所有“修改”操作都返回新字符串,原值不变。
len(s)获取字节长度,utf8.RuneCountInString(s)获取真实字符数(处理中文等Unicode时必须用后者)s[i]得到byte,不是rune;要遍历字符请用for _, r := range s
s[start:end]安全且零分配(只要不越界),例如s[2:5]取第2到第4个字节strings.Builder(比+或fmt.Sprintf更省内存),尤其在循环中切片是引用类型,包含指向底层数组的指针、长度len和容量cap。常见误操作多源于对cap和底层数组共享的理解偏差。
make([]T, len, cap)控制初始容量;直接字面量[]int{1,2,3}容量等于长度append(s, x)——若容量不足会自动扩容(通常翻倍),返回新切片;原切片变量可能失效,务必接收返回值s[1:3]会复用原底层数组,修改它可能影响其他引用同一数组的切片;需要隔离时用newS := append([]T(nil), oldS...)深拷贝s = s[:0](保留底层数组,适合复用),而非s = nil(释放引用,下次append可能重新分配)map是引用类型,但其零值是nil,未初始化就写入会panic。读取不存在的key则返回对应类型的零值,不会报错。
立即学习“go语言免费学习笔记(深入)”;
m := make(map[K]V)或m := map[K]V{}初始化;var m map[K]V只是声明nil mapv, ok := m[k],ok为true才表示key存在(避免把零值误判为“有值”)delete(m, k);清空整个map应遍历+delete,不能直接赋nil(那只是让变量不再指向原map)
sync.RWMutex或改用sync.Map(适用于读多写少场景)字符串重在理解不可变性与Unicode处理,切片关键在掌控底层数组生命周期,map重点在于初始化、存在性检查和并发约束。三者组合使用时(比如用字符串作map键、切片存结构体字段),逻辑就自然清晰了。