Skip to content
Go
Go 常见陷阱汇总

Go 常见陷阱汇总

本文档跨主题汇总了 Go 标准库使用中最容易犯的错误,作为速查清单。


并发与同步

陷阱 后果 检测
复制 sync.Mutex(值传递) 锁失效 go vet
WaitGroup.Add 放在 goroutine 内部 panic: negative counter -race
RWMutex 读锁内获取写锁 死锁 运行时阻塞
sync.Once.Do 内递归调用同一个 Once 死锁 运行时阻塞
time.After 在循环中频繁创建 内存泄漏(channel 不回收) pprof heap
向已关闭 channel 发送 panic 代码审查
读取 channel 时未区分关闭 vs 有值 逻辑错误 v, ok := <-ch
Context 的 cancel 从不调用 goroutine 泄漏 pprof goroutine
sync.Pool 假设 Put 的对象一直存在 对象被 GC 清除 逻辑错误

时间处理

陷阱 正确做法
time.Parse 默认 UTC ParseInLocation
AddDate(0,1,0) 月末溢出 检查结果日期
time.AfterFunc 忘记 Stop 计时器泄漏
defer cancel() 漏写 Context 泄漏
== 比较两个 time.Time Equal()

JSON 编解码

陷阱 后果
JSON 数字反序列化到 interface{} 时精度丢失 大整数变 float64
omitempty 对 struct 不生效 空结构体仍被序列化
默认 HTML 转义 &<> 被转义
nil slice → null,empty slice → [] API 行为不一致
json.UnmarshalDecoder.UseNumber() 不同 数字类型不同
MarshalJSON 返回值没有引号 非法 JSON

I/O 操作

陷阱 正确做法
假设 Read 一次返回所有数据 循环读取或用 io.ReadFull
忽略 Readn>0 时返回的 err 先处理 buf[:n],再检查 err
bufio.Writer 忘记 Flush() 数据丢失
bufio.Scanner 不检查 Err() 截断数据不报错
忘记 resp.Body.Close() HTTP 连接泄漏
os.Exit 跳过 defer 手动清理

路径与文件系统

陷阱 正确做法
字符串拼接路径 dir + "/" + file filepath.Join
filepath.Clean 后不验证路径 检查路径仍在基础目录内
os.Create 截断已有文件 追加用 O_APPEND
defer file.Close() 在任何需要写后检查 用闭包处理 Close 错误

反射

陷阱 后果
对不可寻址 Value 调 SetXxx panic
Int() 调在非整数类型 panic
FieldByName 找不到字段 返回零值(不 panic)
reflect.TypeOf(nil) 返回 nil 检查 nil
reflect.ValueOf(nil) 返回零值 Value 行为与 TypeOf 不同

其他常见错误

陷阱 正确做法
fmt.Sprintf 在热路径中 strconv + strings.Builder
string([]byte) 频繁转换 统一使用一种类型
regexp.Compile 在循环中 全局预编译
nil map 赋值 make(map[...]...)
忽略 error 返回值 始终检查
:= 在错误的 scope 创建新变量 小心 if/for 中的 :=