启用标准库log需设置时间戳、文件行号并输出到控制台和文件,通过SetFlags、SetPrefix和MultiWriter实现,结合debug开关函数D控制日志等级,程序退出前关闭文件确保日志完整写入。
直接用 Go 标准库 log 搭配简单配置就能满足本地调试需求,不需要引入重型日志框架。关键在于让日志带时间、文件名、行号,并输出到控制台和文件双通道,便于实时观察又可回溯。
Go 的 log 包默认输出简陋,但只需几行设置就能升级:
log.SetFlags(log.LstdFlags | log.Lshortfile) —— 加上时间戳和源码位置(如 main.go:23)log.SetPrefix("[DEBUG] ") 统一加前缀,方便 grep 过滤log.Println,改用 log.Printf("msg: %v, err: %v", val, err),更清晰可控本地调试时既要看到实时输出,又要保留记录。不用写文件逻辑,用 io.MultiWriter 一行搞定:
f, _ := os.OpenFile("debug.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
log.SetOutput(io.MultiWriter(os.Stdout, f))
f.Close(),否则最后一段日志可能没刷入磁盘标准库不内置 level,但本地调试可用布尔变量快速控制:
var debugMode = true
func D(msg string, args ...interface{}) { if debugMode { log.Printf("[DEBUG] "+msg, args...) } }
debugMode = false,或通过 -tags=debug + build tag 更灵活控制写个测试入口,运行后立刻确认是否生效:
D("user login, id=%d", 1001),看终端是否显示带时间和文件行号的输出debug.lo
g 文件是否同步追加内容,权限是否正常(尤其 macOS/Linux)os.Truncate(f, 0) 或手动删文件基本上就这些。不复杂但容易忽略细节,比如忘记 Lshortfile 就找不到哪行打的日志,或者没关文件导致日志截断。本地跑通了,后续再考虑 zap、zerolog 等进阶方案也不迟。