filepath.WalkDir可安全遍历过期文件:用time.Now().Add(-72*time.Hour)设阈值,fs.DirEntry.Info()检查ModTime,os.ErrPermission返回fs.SkipDir;删除用os.RemoveAll加retry机制,避免device busy;守护进程需signal.Notify捕获SIGTERM并优雅退出。

如何用 filepath.WalkDir 安全遍历并识别过期文件
直接用 filepath.Walk 有并发风险,且无法跳过权限错误目录;filepath.WalkDir(Go 1.16+)更可控,配合 fs.DirEntry 可避免多次 stat 调用。
- 先用
time.Now().Add(-72 * time.Hour)算出过期时间阈值(比如保留 3 天) - 遍历时对每个
fs.DirEntry调用entry.Info(),检查ModTime()是否早于阈值 - 遇到
os.ErrPermission时返回fs.SkipDir,避免进程卡死 - 注意:
entry.Info()在 symlink 上可能返回目标文件时间,如需按链接自身时间判断,得额外os.Lstat
为什么不能用 os.Remove 直接删,而要用 os.RemoveAll 加重试
单个 os.Remove 对非空目录会报 directory not empty;但 os.RemoveAll 又可能因文件被占用(如日志正被写入)失败,必须处理临时性错误。
- 对每个待删路径,先尝试
os.RemoveAll - 若错误是
text: device or resource busy或access denied,记录后跳过,不 panic - 避免在循环中连续重试——加
time.Sleep(100 * time.Millisecond)再试一次即可,否则可能拖慢整个扫描周期 - 删除前建议加
log.Printf("removing: %s (mod: %v)", path, fi.ModTime()),方便排查误删
守护进程要怎么“守”住,而不是跑完就退出
没有后台化机制的 Go 程序一旦终端关闭或父进程退出,就会被 SIGTERM 杀掉。不能只靠 for range time.Tick(...) 循环。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 用
signal.Notify捕获os.Interrupt和syscall.SIGTERM,优雅停止 ticker - 主 goroutine 阻塞在
select{}等待信号,而非time.Sleep后直接 return - Linux 下若需真正 daemonize(脱离终端),得调用
syscall.Setsid()并重定向os.Stdin/Stdout/Stderr到/dev/null,但多数场景用 systemd 管理更稳妥 - systemd 示例配置里必须设
Type=notify或Type=simple,并禁用RestartSec过短(如 100ms),防止反复崩溃重启掩盖问题
filepath.Match 过滤文件名时容易忽略的通配细节
filepath.Match 不支持 ** 递归匹配,也不等价于 shell glob;它只做单层模式匹配,且 * 不匹配路径分隔符 /。
- 想删所有
.log文件?用"*.log"即可,但不会匹配subdir/app.log - 要跨目录匹配,得在
WalkDir回调里用strings.HasSuffix(entry.Name(), ".log") - 排除临时文件常见写法:
if strings.HasPrefix(name, ".") || strings.HasSuffix(name, "~"),注意.gitignore类规则需另实现 - 正则更灵活但性能差,简单后缀/前缀判断优先用
strings函数
真正麻烦的是 NFS 挂载点上的文件,ModTime 可能不准,且 RemoveAll 易超时;这种场景建议加挂载点白名单校验,或跳过远程文件系统。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










