fsnotify 是 Go 监控文件变化的事实标准,需手动递归监听子目录、启动事件循环、正确解析 Op 位掩码、防抖去重、跨平台兜底及及时关闭 watcher 避免资源泄漏。
用 fsnotify 监控文件变化是最直接的选择
Go 标准库不提供原生文件监听能力,fsnotify 是事实标准。它封装了各平台的底层机制(inotify/kqueue/ReadDirectoryChangesW),不用自己写 syscall。直接 go get github.com/fsnotify/fsnotify 即可使用。
常见错误是只监听目录却没递归处理子目录——fsnotify 默认不递归,必须手动遍历并为每个子目录调用 watcher.Add();另一个坑是监听后忘记启动事件循环,导致 watcher.Events 通道阻塞或漏事件。
- 监听单个文件时,路径必须存在且有读权限,否则
Add()返回 error - 监听目录时,对目录本身有执行(x)权限才可能成功(Linux/macOS)
- Windows 下若文件被其他进程独占打开(如 Excel 编辑中),重命名或删除事件可能收不到
- 事件通道需另起 goroutine 消费,否则会卡住 watcher 内部逻辑
区分文件创建、修改、删除事件要靠 Event.Op 字段
fsnotify.Event 的 Op 是位掩码,不是单一值。不能用 == 判断,得用按位与:
if event.Op&fsnotify.Write == fsnotify.Write {
// 实际可能是 Write|Chmod,但至少发生了写入
}
典型误判场景:文本编辑器保存文件常触发 Write + Chmod,直接比对 event.Op == fsnotify.Write 会失败;又比如 Vim 的 swap 文件临时写入也会发 Write,但你可能只想响应真实内容变更。