Go log包默认输出到stderr,需用os.OpenFile打开文件并调用log.SetOutput()设置;推荐flag组合为os.O_CREATE|os.O_WRONLY|os.O_APPEND;注意关闭文件、缓冲刷新及日志轮转问题。

Go 标准库的 log 包默认只输出到 stderr,不支持直接写文件——得自己套一层 os.File。
怎么让 log 写进文件而不是控制台
核心是把 log.SetOutput() 指向一个打开的 *os.File。不能直接传路径字符串,必须先用 os.OpenFile() 打开或创建文件句柄。
-
os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)是最常用模式:追加写、自动创建、权限合理 - 别用
os.Create()—— 它会清空已有内容,线上日志一重启就丢历史 - 记得在程序退出前调用
file.Close(),否则可能丢失最后几条日志(缓冲未刷出) - 如果日志量大,建议配合
log.SetFlags(log.LstdFlags | log.Lshortfile)控制格式,避免行太长影响可读性
os.OpenFile 的 flag 组合容易错在哪
常见错误是只写 os.O_WRONLY,漏掉 os.O_CREATE 或 os.O_APPEND,导致程序启动失败或日志被覆盖。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
-
os.O_CREATE | os.O_WRONLY | os.O_APPEND:安全组合,推荐始终使用 -
os.O_TRUNC和os.O_APPEND互斥,同时设会导致行为未定义(实际多数系统忽略os.O_APPEND) - Windows 下路径分隔符用
/没问题,Go 运行时自动转换;但硬写\要加转义,易出错,统一用/
要不要用第三方日志库(比如 zap 或 zerolog)
标准库够用,但有硬伤:不支持日志轮转、无结构化输出、并发写文件需自己加锁(log 本身线程安全,但多个 log.Logger 共享同一文件句柄时,写入仍可能交错)。
立即学习“go语言免费学习笔记(深入)”;
- 单机小项目、调试阶段,标准库 +
os.File完全够用 - 需要按天/大小切分日志?必须引入
lumberjack这类轮转封装,或换zap(它内置了WriteSyncer接口,可对接lumberjack.Logger) -
zerolog默认输出 JSON,如果下游日志系统(如 Loki、ELK)吃 JSON,它比标准库省事;否则还得额外解析
真正麻烦的不是“怎么写进文件”,而是“怎么不让日志文件无限增长”和“崩溃时最后一段日志还在缓冲区里”。这两个点,标准库不帮你兜底,得自己想清楚策略再动手。

















