go标准库log通过log.setflags()控制元信息,如log.lstdflags|log.lshortfile可同时输出时间戳和文件行号;setprefix()添加日志前缀;微秒级时间需组合log.lmicroseconds;自定义时间格式须重写output;log.fatal/log.panic禁用于http handler。

Go 标准库 log 不适合直接用于生产服务,但它是调试和 CLI 工具的高效起点——关键在于你能否快速让它输出你真正需要的信息,而不是被默认行为带偏。
如何用 log.SetFlags 控制日志元信息
默认只带 Ldate | Ltime,但调试时往往缺两样:哪行代码打的日志、有没有带前缀。不加 log.Lshortfile,你得靠 grep 源码找位置;不加 log.LstdFlags,时间格式可能不统一(比如 Ldate 和 Ltime 分开设,中间没空格)。
-
log.SetFlags(log.LstdFlags | log.Lshortfile)是最常用组合:时间 + 文件名:行号 - 想省空间?去掉
LstdFlags,只留log.Lshortfile | log.Lmicroseconds,获得高精度时间戳+源码位置 -
log.Llongfile会输出完整路径,CI/CD 日志里容易暴露项目根目录,开发机可用,别上生产 - 一旦调用
SetFlags,所有后续日志(包括第三方库未重定向的log.Print)都会受影响
为什么 log.SetOutput 容易导致日志“消失”
不是代码没执行,而是日志写进了没人看的地方。常见错误是:os.OpenFile 失败后没处理 err,直接跳过 SetOutput,结果日志继续打到 stderr —— 而你正盯着文件看。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 必须检查
os.OpenFile返回的err,否则文件创建失败时log.SetOutput(nil)会让所有日志静默丢弃 - HTTP server 启动前就调用
SetOutput,但没defer f.Close(),会导致文件句柄泄漏,几天后too many open files - 多个 goroutine 并发写同一文件?
log本身线程安全,但底层文件写入不保证原子性,短日志可能被截断,长日志建议加sync.Mutex包一层 - 别在 handler 里反复调用
SetOutput—— 它是全局生效的,一次设置,全程有效
log.Printf 与敏感信息泄露风险
用 log.Printf("user %s login, token %s", user, token) 看似方便,实则把凭证直接刷进日志文件。线上环境只要扫一眼日志,就能拿到 token。
- 永远用占位符:
log.Printf("user %s login, token %s", user, "[REDACTED]") - 如果必须记录原始值(比如 debug 阶段),至少加运行时开关:
if debug { log.Printf("token: %s", token) } -
log.Print拼字符串更危险:log.Print("token " + token)无法被静态扫描工具识别脱敏点 - 第三方库(如
database/sql)内部也用log,它们不会自动脱敏 —— 若需审计,得重定向其输出并过滤
log.Fatal 在 HTTP handler 中的致命误用
它不是“记录错误然后返回 500”,而是整个进程退出。一个请求出错,整台机器的服务就挂了。
-
log.Fatal等价于log.Print() + os.Exit(1),defer不执行,HTTP 连接直接断开,客户端收不到任何响应 - 正确做法:用
log.Printf记录错误,再显式http.Error(w, "internal error", http.StatusInternalServerError) -
log.Panic同理,除非你真想触发 recover(且确保上层有兜底),否则别在 handler 里用 - CLI 工具中
log.Fatal可接受,因为单次运行、无并发、无状态延续
标准 log 没有上下文字段绑定能力,trace ID、request ID、用户 ID 都得手动拼进每条日志字符串里 —— 看似简单,但漏一条就断链。这点在排查分布式请求时最痛,而很多人直到线上告警才意识到。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










