os.removeall不能直接删过期文件,需先用os.stat获取modtime()并与当前时间比对;推荐统一快照now := time.now()后用now.after(fi.modtime().add(24*time.hour))判断,避免反复调用time.now()导致抖动漏删。

os.RemoveAll 不能直接删过期文件,得先判断是否过期
Go 没有内置“按时间自动删文件”的机制,os.RemoveAll 只管删目录,不管时间。你要自己用 os.Stat 拿到文件的 ModTime(),再跟当前时间比对。别写成 time.Since(fi.ModTime()) > 24*time.Hour —— 这种写法每次调用都重新取系统时间,可能因纳秒级抖动导致同一批文件有的删、有的漏。
推荐做法是统一快照:
- 在清理循环开头调一次
now := time.Now() - 所有判断都用
now.After(fi.ModTime().Add(24 * time.Hour))或now.Sub(fi.ModTime()) > 24*time.Hour - 避免在
filepath.WalkDir回调里反复调time.Now()
扫描时别用 for range map,临时文件路径要存结构体里
如果你把临时文件路径存在 map[string]time.Time 里,想定时遍历删除,千万别用 for k := range cache 然后直接 delete(cache, k) —— Go 的 map 迭代本身不保证顺序,且并发读写会 panic。更糟的是,delete 会改变 map 内部状态,导致迭代器失效,下一轮 range 可能跳过条目或 panic。
安全做法是:
- 用切片存路径:
var tempFiles []string,创建时append进去 - 清理时遍历切片,对每个路径调
os.Stat+ 时间判断 +os.Remove - 删成功后从切片里
copy覆盖(或用新切片重建),别边遍历边删原 slice 元素
Windows 下 os.Remove 失败常见于文件被占用,不是权限问题
Linux/macOS 上删不掉通常是父目录无写权限,用 ls -ld /path/to/parent 查;但 Windows 下更大概率是文件被其他进程锁住 —— 比如 VS Code 正在预览、杀毒软件正在扫描、甚至 Explorer 打开了该文件夹。此时 os.Remove 返回的错误是 syscall.ERROR_SHARING_VIOLATION,不是 syscall.EACCES。
在 Golang 中使用 samber/hot 进行内存缓存,支持 LRU、LFU、TinyLFU、W‑TinyLFU、S3FIFO、ARC、TwoQueue、SIEVE、FIFO 等淘汰算法,提供 TTL、缓存加载器及分片功能。
应对策略很简单:
- 先尝试
os.Chmod(path, 0644)解除只读(尤其从 zip 解压来的文件常带只读属性) - 最多重试 2 次,每次
time.Sleep(100 * time.Millisecond) - 用
errors.Is(err, syscall.ERROR_SHARING_VIOLATION)判断,别用字符串匹配
t.Cleanup 不适用于长期服务,信号捕获才是正解
t.Cleanup 在测试里很稳,但生产服务跑几天甚至几个月,不能靠它。主 goroutine 收到 SIGTERM 后如果直接 os.Exit(),所有 defer 都不会执行,临时文件必然残留。
必须换路径:
- 用
signal.Notify(c, os.Interrupt, syscall.SIGTERM)捕获退出信号 - 把所有待清理路径注册进一个全局列表(比如
var cleanupPaths []string) - 收到信号后,逐个调
os.RemoveAll或os.Remove,并加日志记录结果 - 清理完再
os.Exit(0),而不是在 signal handler 里直接 exit
真正容易被忽略的是:临时文件路径必须绝对化且校验前缀。传给 os.RemoveAll 前一定要过一遍 filepath.Abs,再确认是否以 os.TempDir() 开头 —— 否则 os.RemoveAll("../config.yaml") 这种误传会直接删掉关键配置。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










