在Linux中,我们知道有一个inotify的软件,它可以监听文件或者目录的变化,我们可以根据变化做不同的操作。
现在有一个Golang开发的工具也有这个功能,叫做fsnotify。
官方文档:https://godoc.org/github.com/fsnotify/fsnotify
从官方文档看其实现流程很简单,就只有三个结构体,一个监听,一个获取事件,一个处理。
下面简单介绍其使用。
我们先看官方的一个例子:
package mainimport ("log""github.com/fsnotify/fsnotify")func main() {watcher, err := fsnotify.NewWatcher()if err != nil {log.Fatal(err)}defer watcher.Close()done := make(chan bool)go func() {for {select {case event, ok := <-watcher.Events:if !ok {return}log.Println("event:", event)if event.Op&fsnotify.Write == fsnotify.Write {log.Println("modified file:", event.Name)}case err, ok := <-watcher.Errors:if !ok {return}log.Println("error:", err)}}}()err = watcher.Add("E:\\test")if err != nil {log.Fatal(err)}<-done}
然后我们创建一个测试文件,看日志输出如下:
其使用比较简单:
- 调用NewWatcher创建一个监听器
- 调用监听器的Add方法增加监听的文件或目录
- 同时会起一个协程不断获取监听事件,然后根据监听事件做不同的操作
其事件类型如下:
type Event struct {Name string // Relative path to the file or directory.Op Op // File operation that triggered the event.}
该类型只有两个字段,Name表示发生事件的文件名或目录,Op表示具体的事件。其中Op中有5个值,如下:
const (Create Op = 1 << iotaWriteRemoveRenameChmod)
上面是监听单个目录或者文件,如果要监听目录及其子目录的话,就需要自己实现了,如下:
package mainimport ("log""os""path/filepath""github.com/fsnotify/fsnotify")func watchDir(watcher *fsnotify.Watcher,dir string) {// 遍历子目录filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {// 判断是否为目录,只需要监听目录,目录下的文件变化就可以进行相应操作if info.IsDir(){path, err := filepath.Abs(path)if err != nil {log.Println(err)return err}// 然后将其加入监听if err := watcher.Add(path);err!=nil{log.Printf("watch %s failed. err = %s",path,err.Error())return err}}return nil})}func main() {watcher, err := fsnotify.NewWatcher()if err != nil {log.Fatal(err)}defer watcher.Close()done := make(chan bool)go func() {for {select {case event, ok := <-watcher.Events:if !ok {return}log.Println("event:", event)if event.Op&fsnotify.Write == fsnotify.Write {log.Println("modified file:", event.Name)}if event.Op&fsnotify.Create != 0{log.Println("Created file:", event.Name)}case err, ok := <-watcher.Errors:if !ok {return}log.Println("error:", err)}}}()//err = watcher.Add("E:\\test")//if err != nil {// log.Fatal(err)//}watchDir(watcher,"E:\\test")<-done}
然后我们操作子目录,也会有相应的事件发生。
