
本文介绍如何使用 zap 库为不同日志级别(info、warn、error 等)配置终端彩色输出,并同时将各等级日志分别写入独立文件(如 info.log、error.log),涵盖开发与生产环境的 encoderconfig 与 core 组合定制。
本文介绍如何使用 zap 库为不同日志级别(info、warn、error 等)配置终端彩色输出,并同时将各等级日志分别写入独立文件(如 info.log、error.log),涵盖开发与生产环境的 encoderconfig 与 core 组合定制。
Zap 默认不支持开箱即用的彩色控制台日志,但其 zapcore 提供了高度可定制的编码器(Encoder)和核心(Core)机制,允许我们组合多个 WriteSyncer(如 os.Stdout 和文件句柄),并为不同日志级别指定不同的 EncoderConfig 行为——包括颜色渲染与输出目标。
✅ 控制台彩色输出(仅限开发环境)
Zap 内置了 zapcore.CapitalColorLevelEncoder,它会为 Debug、Info、Warn、Error、DPanic、Panic、Fatal 级别自动添加 ANSI 颜色前缀(如绿色表示 Info,红色表示 Error)。该编码器仅在 io.Writer 支持颜色(如终端)且 DevelopmentEncoderConfig 被启用时生效:
config := zap.NewDevelopmentConfig()
config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
logger, _ := config.Build()
logger.Info("This appears in green") // ✅ 彩色
logger.Error("This appears in red") // ✅ 彩色⚠️ 注意:CapitalColorLevelEncoder 仅影响 level 字段的颜色,不改变消息体或时间戳;且生产环境应禁用颜色(避免日志解析失败),推荐仅在 DevelopmentConfig 下使用。
✅ 按级别分流写入不同文件
Zap 不提供“自动按 level 分文件”的内置功能,需手动构造多个 zapcore.Core 并通过 zapcore.LevelEnablerFunc 过滤日志级别,再用 zapcore.NewTee 合并:
import (
"os"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func newLogger() *zap.Logger {
// 创建文件 WriteSyncer
infoFile, _ := os.OpenFile("info.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
warnFile, _ := os.OpenFile("warn.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
errorFile, _ := os.OpenFile("error.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
// 定义各文件对应的 encoder(建议统一为 ProductionEncoderConfig)
encoderCfg := zap.NewProductionEncoderConfig()
encoderCfg.TimeKey = "time"
encoderCfg.EncodeTime = zapcore.ISO8601TimeEncoder
// 构建各 level 的 core
infoCore := zapcore.NewCore(
zapcore.NewJSONEncoder(encoderCfg),
zapcore.AddSync(infoFile),
zapcore.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl == zapcore.InfoLevel
}),
)
warnCore := zapcore.NewCore(
zapcore.NewJSONEncoder(encoderCfg),
zapcore.AddSync(warnFile),
zapcore.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl == zapcore.WarnLevel
}),
)
errorCore := zapcore.NewCore(
zapcore.NewJSONEncoder(encoderCfg),
zapcore.AddSync(errorFile),
zapcore.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl >= zapcore.ErrorLevel
}),
)
// 合并所有 core(支持多目标、多级别)
core := zapcore.NewTee(infoCore, warnCore, errorCore)
// 可选:添加彩色控制台输出(仅开发)
consoleEncoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
consoleCore := zapcore.NewCore(
consoleEncoder,
zapcore.Lock(os.Stdout),
zapcore.DebugLevel, // 全量输出到控制台
)
core = zapcore.NewTee(core, consoleCore)
return zap.New(core, zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel))
}
func main() {
logger := newLogger()
defer logger.Sync() // 刷盘关键!
logger.Info("this goes to info.log and stdout (colored)")
logger.Warn("this goes to warn.log and stdout")
logger.Error("this goes to error.log and stdout")
}⚠️ 关键注意事项
-
defer logger.Sync()必须调用:否则异步日志可能丢失; -
文件句柄需自行管理生命周期:示例中未关闭文件,实际项目建议封装
Close()方法; -
性能考量:频繁创建
OpenFile或未复用WriteSyncer会影响吞吐,生产环境推荐使用lumberjack.Logger实现轮转; -
颜色兼容性:
CapitalColorLevelEncoder依赖终端支持 ANSI,CI/容器环境通常禁用,可通过isTerminal()检测后动态启用; -
级别覆盖逻辑:
LevelEnablerFunc决定某条日志是否进入该 Core,务必避免重叠或遗漏(例如ErrorLevel应包含DPanic/Panic/Fatal)。
综上,Zap 的灵活性源于 Core 的组合能力。通过 NewTee + 多 LevelEnablerFunc + 多 WriteSyncer,你既能实现彩色调试体验,又能满足审计级日志分级落盘需求——无需第三方封装,纯官方 API 即可达成。

















