-
本文用完整工作流回答 Go map 并发读写为什么会崩:先复现 fatal error 和 data race,再定位共享 map,最后按场景选择 RWMutex、sync.Map 或 channel 收口,并给出上线前检查清单。
-
本文用完整工作流讲解 Go defer 的常见疑问:为什么 defer fmt.Println(i) 打印旧值,defer 注册时参数何时保存,闭包为什么能读到新值,命名返回值如何在 defer 中包装错误,以及多个 defer 为什么按倒序触发。
-
本文解释 Go for range 中 goroutine 打印错值的问题,区分 Go 1.22 新循环变量语义和旧模块行为,并给出版本检查、代码排查、兼容写法和验证清单。
-
本文用 Go 接口返回 JSON 的现象入手,逐步验证 nil slice 和空 slice 在 len、cap、底层数组、json.Marshal 输出上的区别,并给出 API 响应保持 [] 的初始化方案。
-
本文回答 Go 里 sync.Once 为什么能保证函数只执行一次、多个协程同时调用时内部做了什么、以及在配置加载、单例初始化和懒加载里怎么安全复用。
-
本文回答 Go range 循环变量取地址为什么容易踩坑:旧语义下多个指针可能指向同一个循环变量,Go 1.22 后每轮变量语义改变,但如果目标是修改原切片元素,仍应使用索引取址。
-
用两个最小复现解释 Go slice 的 append 行为:当 cap 够用时会复用底层数组,原 slice 可能被间接改动;当 cap 不够时会分配新数组,后续修改互不影响。
-
用 Go 的接口值模型解释 typed nil 坑:接口变量由动态类型和动态值两部分组成,只有两者都为空才等于 nil;当 error 接口保存了 nil 指针但动态类型存在时,err != nil 会成立。
-
围绕 Go defer 在循环中的常见误用,解释为什么文件、连接、锁等资源会等到函数返回才释放,并给出函数拆分、显式关闭和错误处理的实战写法。
-
通过一个 Go map 并发读写 panic 案例,解释普通 map 为什么不是并发安全的,并对比 RWMutex、sync.Map、分片 map 和 channel 拥有者模式的适用场景。
-
atomic包基于CPU原子指令实现无锁并发操作。通过CAS操作实现变量的安全更新,避免使用锁带来的性能开销。相似问题及优化建议:CAS失败如何处理?atomic和Mutex区别?高并发如何选择同步方式?
-
Go语言的map在负载因子超过约6.5或溢出桶数量过多时触发扩容,并采用渐进式迁移而不是一次性重哈希。map底层使用哈希桶结构,每个桶可存储8个键值对。当元素增加导致负载过高时,会分配新的桶数组。旧桶中的数据不会一次性迁移,而是在后续写操作中逐步搬迁,减少性能抖动。同时删除元素过多时也可能触发等量扩容优化结构。相似问题及优化建议:map为什么不是线程安全的?因为底层未加锁。如何减少扩容带来的性能问题?可以提前指定容量。高并发场景下如何使用map?可使用sync.Map或加Mutex保护。
-
Go语言的select在多个case同时满足条件时采用伪随机算法选择执行分支,以避免饥饿问题。编译器会将case顺序打乱,通过runtime中的随机机制遍历case列表,保证公平性。这样可以防止固定顺序导致某些case长期得不到执行。相似问题及优化建议:select是否绝对公平?select如何避免阻塞?高并发场景如何设计select结构?避免case过多。
-
sync.Map适合读多写少的高并发场景。内部采用分段锁和只读副本结构优化读性能,不适合频繁写入场景。相似问题及优化建议:sync.Map和map+Mutex区别?什么时候不用sync.Map?如何优化高并发map?
-
sync.Pool用于缓存临时对象,减少频繁分配和回收带来的GC压力。对象放入Pool后可能在GC时被清空,因此适用于短生命周期对象缓存。适合高并发场景下减少内存分配次数,例如缓冲区复用。相似问题及优化建议:sync.Pool什么时候会被清空?sync.Pool适合长期对象缓存吗?如何正确使用对象池避免内存泄漏?