Golang 監控文件夾內文件的增刪改(包括子文件夾)
你需要自己處理log部分
package main import ( "crypto/md5" "fmt" "go-admin/log" "os" "path/filepath" "time" "github.com/fsnotify/fsnotify" ) type FileChangeCallback func(absfpname string) type ConfigFileWatcher struct { WatchedDirectory string // 監控目錄 FileSuffix string // 監控的文件類型 OnFileChange FileChangeCallback // 相關文件有變更就會調用這個回調 } func (cfw ConfigFileWatcher) WatchConfigFileChanges() { // 注意如果該文件被其他程序占用的話會讀取不出內容的。比如vscode打開了文件 getFileHash := func(filename string) (string, error) { data, err := os.ReadFile(filename) if err != nil { return "", err } return fmt.Sprintf("%x", md5.Sum(data)), nil } watcher, err := fsnotify.NewWatcher() if err != nil { log.Fatal("WatchConfigFileChanges", err.Error(), "") } defer watcher.Close() dir := cfw.WatchedDirectory fileInfos := make(map[string]string) err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { err = watcher.Add(path) if err != nil { log.Fatal("WatchConfigFileChanges", err.Error(), "") } } else { if filepath.Ext(path) == ".yml" { hash, err := getFileHash(path) if err != nil { log.Fatal("WatchConfigFileChanges", "獲取文件哈希出錯:%s", err.Error()) } else { fileInfos[path] = hash } } } return nil }) if err != nil { log.Fatal("WatchConfigFileChanges", "%s", err.Error()) } fmt.Println("開始監控...") var lastEventTime time.Time interval := 500 * time.Millisecond // 設置等待時間為500毫秒 func() { for { select { case event, ok := <-watcher.Events: if !ok { return } if (event.Op&fsnotify.Write == fsnotify.Write || event.Op&fsnotify.Create == fsnotify.Create) && filepath.Ext(event.Name) == cfw.FileSuffix { // 檢查時間間隔,如果在等待時間內則跳過 if time.Since(lastEventTime) < interval { continue } // 獲取文件的最新MD5值 newHash, err := getFileHash(event.Name) if err != nil { log.Fatal("WatchConfigFileChanges", "獲取文件哈希出錯:%s", err.Error()) } else { // 對比MD5值,確認文件內容是否發生了變化 if prevHash, exists := fileInfos[event.Name]; exists && prevHash == newHash { fmt.Println("文件未更改:", event.Name) log.Log("WatchConfigFileChanges", "文件未更改:%s", event.Name) } else { fileInfos[event.Name] = newHash absPath, _ := filepath.Abs(event.Name) log.Log("WatchConfigFileChanges", "文件修改或創建:%s", absPath) cfw.OnFileChange(absPath) } } // 更新最后事件時間 lastEventTime = time.Now() // 因為fsnotify源碼常量定義錯了。Rename和Remove搞反了 } else if (event.Op&fsnotify.Rename == fsnotify.Rename) && filepath.Ext(event.Name) == cfw.FileSuffix { // 檢查時間間隔,如果在等待時間內則跳過 if time.Since(lastEventTime) < interval { continue } absPath, _ := filepath.Abs(event.Name) fmt.Println("文件被刪除:", absPath) cfw.OnFileChange(absPath) // 更新最后事件時間 lastEventTime = time.Now() } case err, ok := <-watcher.Errors: if !ok { return } log.Fatal("WatchConfigFileChanges", "錯誤:%s", err.Error()) } } }() }

浙公網安備 33010602011771號