Zap默认日志打在终端且无颜色,是因为NewProduction()输出无色JSON到stdout,而NewDevelopment()才启用ANSI彩色输出(仅限支持终端);CI或重定向时自动禁用颜色。

Zap 是 Go 里性能最好的结构化日志库之一,但直接引入不等于高效——它默认不输出到文件、不自动轮转、不带上下文追踪,这些都得手动配。
为什么 go get go.uber.org/zap 后日志还是打在终端且没颜色?
Zap 默认使用 zap.NewProduction() 或 zap.NewDevelopment(),前者输出 JSON 到 stdout(无颜色),后者输出带颜色的文本但仍是 stdout;它不依赖终端着色库,颜色只在 zap.NewDevelopment() 下对支持 ANSI 的终端生效,CI 环境或重定向到文件时会自动禁用。
- 开发时想看彩色日志:用
zap.NewDevelopment(),别自己套io.MultiWriter加 color 包 - 生产环境要 JSON:坚持用
zap.NewProduction(),别试图“美化”JSON 输出——下游 ELK 或 Loki 会解析,人眼不该读它 - 想同时输出到终端和文件?必须显式构造
zapcore.Core,不能只改EncoderConfig
如何让 Zap 自动按天轮转日志文件?
Zap 本身不提供轮转功能,必须组合 lumberjack.Logger(第三方)或 fsnotify + 定时检查——推荐前者,轻量可靠。
- 先
go get gopkg.in/natefinch/lumberjack.v2 - 创建
lumberjack.Logger实例,设置Filename、MaxSize(MB)、MaxBackups、MaxAge(天) - 把它的
io.WriteSyncer传给zapcore.AddSync,再传给zapcore.NewCore - 注意:
lumberjack的Rotate是同步阻塞的,高并发写日志时可能卡住——如果 QPS > 5k,建议加缓冲 channel 或换file-rotatelogs
为什么 logger.With(zap.String("uid", "123")) 后,后续所有日志都带 uid?
这是 Zap 的字段复用机制:返回的新 *zap.Logger 是原 logger 的 clone,携带了已附加的字段。它不是全局状态,但容易误以为“污染了全局 logger”。
立即学习“go语言免费学习笔记(深入)”;
- 长期存在的上下文字段(如服务名、主机名)适合用
With()初始化根 logger - 请求级字段(如 trace_id、user_id)必须在 handler 内部用
logger.With(...).Info(...),别存成包变量 - 字段太多时性能下降明显:Zap 对字段数敏感,超过 10 个字段时,
Reflect编码比String慢 3 倍以上——优先用zap.String、zap.Int,少用zap.Any
真正难的不是初始化 Zap,而是决定哪些字段该进日志、哪些该丢弃,以及轮转策略是否匹配你的运维链路——比如 Kubernetes 里往 stdout 写 JSON,就别硬上 lumberjack;而裸机部署又没日志采集 agent,才需要文件轮转和压缩。


















