应避免在高频路径直接调用 log.Printf/Println,因其同步写入、反射格式化、锁竞争和调用栈检查引发性能瓶颈;推荐使用 zap 等结构化日志库,预分配缓冲、跳过反射、支持异步写入,并按需控制日志等级、禁用 Lshortfile、复用缓冲、避免临时结构体创建。

避免在 hot path 中直接调用 log.Printf 或 log.Println
Go 标准库的 log 包默认使用同步写入 + 反射格式化,每次调用都会触发锁、时间戳生成、调用栈检查(如果启用了 log.Lshortfile)和字符串拼接。在高并发或高频路径(比如 HTTP handler 内部、循环体中)直接打日志,很容易成为性能瓶颈。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 用结构化日志库替代,如
zap(推荐zap.L().Info配合zap.String等字段函数),它预分配缓冲、跳过反射、支持异步写入 - 对非关键路径日志,可先判断日志等级再构造内容,例如:
if logLevel >= LogLevelDebug { logger.Debug("user_id", zap.Int64("id", userID), zap.String("action", "login")) } - 绝不把
fmt.Sprintf结果传给log.Printf——这会强制提前格式化,即使日志被等级过滤掉也白耗 CPU
禁用 log.Lshortfile 和 log.Llongfile 生产环境
这两个 flag 会让每次日志输出都调用 runtime.Caller 获取文件名与行号,开销显著(尤其在 goroutine 密集场景)。压测中常见 runtime.Caller 占 CPU profile 5%~15%。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 生产环境初始化
log.SetFlags(0)或至少去掉log.Lshortfile;调试时再临时开启 - 如果真需要定位位置,改用 zap 的
With(zap.Stringer("caller", zap.Any("caller", zap.StringerFunc(func() string { return callerString() }))这类按需计算方式(但一般不推荐) - 更稳妥的做法是:用追踪 ID(如
X-Request-ID)关联日志 + 链路追踪系统(Jaeger / OpenTelemetry),而非依赖文件行号
用 sync.Pool 复用日志缓冲或结构体实例
某些自定义日志封装或中间件中,频繁创建临时 map、[]interface{}、bytes.Buffer 容易触发 GC 压力。标准 log 不暴露缓冲控制,但 zap / zerolog 等库允许注入自定义 Encoder 或复用 Event 实例。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- zerolog 支持
zerolog.NewConsoleWriter(func(w *zerolog.ConsoleWriter) { w.Out = os.Stdout }),其内部已用sync.Pool管理 buffer;若自己封装,务必对bytes.Buffer或 JSON encoder 实例做池化 - 避免在日志函数内 new struct 或 map:例如不要写
log.Info(map[string]interface{}{"uid": u.ID, "ts": time.Now()}),而应拆成字段传参 - zap 提供
logger.WithOptions(zap.AddCallerSkip(1)),但注意 skip 层数本身也依赖runtime.Caller,慎用在 hot path
异步写入要小心丢日志和 panic 风险
zap 的 zap.NewAsync 或自建 channel + goroutine 日志队列看似能解耦,但引入新问题:进程退出时未 flush 的日志丢失、channel 满导致阻塞或 panic、OOM(buffer 积压)。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- zap 异步模式下,务必在
main退出前调用zap.L().Sync(),且该调用可能阻塞数秒——需配合os.Interrupt信号处理 - 不要用无缓冲 channel 做日志队列;缓冲大小设为 1024~8192,并监控
len(ch)告警 - 更稳的选择是 zap 的
WriteSyncer组合:例如用lumberjack.Logger做轮转 +zapcore.Lock保证线程安全,不引入额外 goroutine
log.Printf("req: %+v", r) 把整个 request struct 反射序列化了。











