go日志写入文件必须用os.openfile配os.o_create|os.o_wronly|os.o_append标志组合,缺一不可;漏o_append会清空日志,漏o_create则文件不存在时失败;路径含子目录需先os.mkdirall。

Go 默认日志输出到终端,要写入文件必须显式替换输出目标;不改 log.SetOutput 或不传正确 os.File 句柄,日志就永远不会进文件。
os.OpenFile 参数缺一不可
常见错误是漏掉 os.O_APPEND 导致每次重启清空日志,或漏 os.O_CREATE 在文件不存在时静默失败。
-
os.O_CREATE | os.O_WRONLY | os.O_APPEND是生产环境最安全的组合,三者必须同时存在 -
0644权限只在 Linux 新建文件时生效,Windows 完全忽略——别指望靠它限制读写 - 如果日志路径含子目录(如
"logs/app.log"),需提前调用os.MkdirAll("logs", 0755),否则OpenFile报no such file or directory
log.SetOutput 和 log.New 的选择场景
全局日志用 log.SetOutput 最快,但所有模块共用同一前缀和格式;多模块隔离必须用 log.New。
- 单服务、单日志文件:直接
log.SetOutput(file),后续所有log.Println都进该文件 - HTTP 请求、DB 查询、任务调度各需不同格式:为每个模块创建独立
*log.Logger,比如accessLog := log.New(accessFile, "http: ", log.LstdFlags) -
log.New返回的 logger 是线程安全的,无需额外加锁;但若自己绕过它直接调file.Write(),就必须手动加sync.Mutex
lumberjack 轮转配置最容易踩的坑
MaxSize 单位是字节不是 MB,MaxBackups: 0 表示“不留备份”,不是“无限保留”——这两个错配会导致日志莫名消失。
- 设
MaxSize: 100 * 1024 * 1024才是 100MB;写成100就是每 100 字节切一次 -
MaxBackups: 0→ 当前日志被轮转后,旧文件立即删除;要保留全部历史,得设一个足够大的数(如999)并配合MaxAge -
Compress: true启用 gzip 压缩,但会增加 CPU 开销;小文件(
真正麻烦的不是写第一行日志,而是确保文件句柄在整个程序生命周期内不被意外关闭、不被多个 goroutine 竞争写入、也不因权限或路径问题在某次部署后突然失效。这些细节在本地跑通不代表生产稳定。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











