在 Go 语言中,日志写入失败通常不是“致命错误”,但必须定位原因并做兜底处理。下面按常见原因 → 排查方法 → 解决方案来说明。
f, err := os.OpenFile("app.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
// 常见:权限不足、目录不存在
}
✅ 常见错误:
permission deniedno such file or directoryno space left on device✅ 排查:
df -h
rm 或 logrotate 移动✅ 表现:
✅ 建议:
sync.Mutexlog.SetOutput + 单 logger 实例如 logrus、zap、zerolog:
if err != nil {
fmt.Println("日志写入失败:", err)
}
⚠️ 注意:
log.Println("xxx") // 默认不返回错误
type errorWriter struct {
w io.Writer
err error
}
func (ew *errorWriter) Write(p []byte) (n int, err error) {
n, err = ew.w.Write(p)
if err != nil {
ew.err = err
}
return
}
f, err := os.Stat("app.log")
fmt.Println(f, err)
log.SetOutput(io.MultiWriter(
logFile,
os.Stderr,
))
✅ 日志文件失败 → 至少还能看到 stderr
defer func() {
if r := recover(); r != nil {
fmt.Println("日志系统异常:", r)
}
}()
func reopenLog() {
f, err := os.OpenFile("app.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err == nil {
log.SetOutput(f)
}
}
✅ 解决 logrotate 问题
log := logrus.New()
log.SetOutput(os.Stdout)
logger, _ := zap.NewProduction()
defer logger.Sync()
✅ 日志写入失败时的黄金原则:
不能因为日志失败导致主流程崩溃
建议:
如果你愿意,可以把具体代码或报错信息贴出来(比如 logrus / zap 使用方式),我可以直接帮你定位问题。