您的位置:首页 >Go 中安全配置多个日志协程方法
发布于2026-04-19 阅读(0)
扫一扫,手机访问

本文详解为何多个 goroutine 共享 log.SetOutput() 会导致日志全部写入最后一个文件,并提供基于独立 log.Logger 实例的正确实现方案,确保每个 LogWorker 写入专属日志文件。
本文详解为何多个 goroutine 共享 `log.SetOutput()` 会导致日志全部写入最后一个文件,并提供基于独立 `log.Logger` 实例的正确实现方案,确保每个 LogWorker 写入专属日志文件。
问题根源在于:Go 标准库的 log 包使用全局变量管理默认 logger(log.std),而 log.SetOutput() 和 log.SetFlags() 会直接修改该全局实例。当多个 LogWorker.Work() 并发调用 log.SetOutput(&lumberjack.Logger{...}) 时,后执行的 goroutine 会覆盖前者的输出目标——最终所有 log.Println() 调用都流向最后一个设置的 lumberjack.Logger,导致仅生成一个日志文件(如 event_3),其余 worker 彻底失效。
✅ 正确做法是为每个 worker 创建*独立的 `log.Logger实例**,而非复用全局 logger。修改LogWorker.Work` 方法如下:
func (lw *LogWorker) Work(evChannel <-chan Event) {
fmt.Printf("LogWorker started: %s\n", lw.FileName)
// ✅ 为每个 worker 创建专属 logger,避免全局污染
lg := log.New(&lumberjack.Logger{
Filename: lw.FileName,
MaxSize: lw.MaxSize,
MaxBackups: lw.MaxBackups,
MaxAge: lw.MaxAge,
}, "", 0) // prefix 为空,flag 为 0(不加时间戳等)
// ✅ 使用 range 遍历通道,支持优雅关闭
for event := range evChannel {
lg.Println(Csv(event))
}
}关键改进点说明:
? 补充建议:
通过以上重构,四个 LogWorker 将严格按预期分别写入 event_0, event_1, event_2, event_3 四个独立文件,真正实现并发日志分流。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9