
go 程序中使用 recover() 捕获 panic 后,若依赖 glog 记录错误,需显式调用 glog.flush() 才能强制将缓冲日志写入目标文件,否则日志可能丢失或落至系统日志(如 /var/log/messages)。
go 程序中使用 recover() 捕获 panic 后,若依赖 glog 记录错误,需显式调用 glog.flush() 才能强制将缓冲日志写入目标文件,否则日志可能丢失或落至系统日志(如 /var/log/messages)。
在 Go 的 glog 日志库中,所有日志输出默认是缓冲写入的:日志内容先暂存于内存缓冲区,仅在特定时机(如定时 flush、程序正常退出、或显式调用 glog.Flush())才真正落盘到指定日志文件(如 INFO, ERROR 等级别对应的文件)。当 panic 发生并被 recover() 捕获后,函数虽能继续执行 defer 逻辑,但若未主动触发 flush,缓冲区中的日志(包括 glog.Errorf 写入的内容)将不会写入磁盘,而是随 goroutine 结束而丢弃——此时 glog 可能退回到默认行为,将日志输出至标准错误(stderr),进而被系统 syslog 拦截并写入 /var/log/messages。
✅ 正确做法是在 defer 函数中 recover() 后立即调用 glog.Flush():
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
defer func() {
if r := recover(); r != nil {
glog.Errorf("Recovered from panic: %v", r)
glog.Flush() // ✅ 关键:强制刷新缓冲区,确保日志写入目标文件
}
}()
panic("THIS IS A PANIC") // 注意拼写修正
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}
⚠️ 注意事项:
- glog.Flush() 是同步阻塞操作,应避免在高频路径中滥用;但在 panic 恢复场景下,其开销可接受且必要。
- glog 已不再积极维护(官方推荐转向 log/slog 或结构化日志库如 zap),新项目建议优先评估现代替代方案。
- 若使用 glog,务必在 main() 函数退出前也调用一次 glog.Flush(),以兜底保障主流程日志不丢失。
- glog 的日志文件路径由 -log_dir 参数控制,确保启动时已正确配置(如 ./myapp -log_dir=./logs)。
总结:panic 不等于进程崩溃(crash),recover() 可使程序继续运行;但 glog 的缓冲机制要求开发者对关键日志主动 flush。忽略 Flush() 是导致“日志消失”现象的根本原因——这不是限制,而是设计契约,需显式遵守。











