概要
Goでファイル監視の方法についての記事です。
Goの標準パッケージではファイル監視の機能は提供されていないが、 github.com/fsnotify/fsnotify を使ったファイル監視のやり方をまとめます。
fsnotifyについて
github.com/fsnotify/fsnotify
各プラットフォーム・OSに対応したファイル変更通知機能(inotifyシステムコールなど)を提供するライブラリです。
主な使い方
ざっくり整理すると、以下の流れになります。
- ファイル監視用のwatcherを作成する。
- watcher.Addにより監視対象とするパスを追加
- watcherがEvents, Errorsというチャネルを持っており、特定のファイルに対するイベントが発生した場合、チャネルにメッセージが送信されるのでそれを受信して処理を行う。
下記から、指定したディレクトリ配下の特定のファイルへのイベントを監視するコードについて説明します。
特定のファイルのみ更新したい場合
上記にあるように、watcher.Addで特定のファイルを指定するのでなく、そのファイルが属するディレクトリを指定し、Eventを監視し、Event.Nameをチェックして必要なファイルのみフィルタリングしてください。
./tmp ディレクトリ配下のtarget.txt
への変更があった場合にEventを表示させる例を示します。
// fsnotifyで特定のファイルを監視 package main import ( "log" "github.com/fsnotify/fsnotify" ) func main() { watcher, err := fsnotify.NewWatcher() if err != nil { log.Fatal(err) } defer watcher.Close() go func() { for { select { case event, ok := <-watcher.Events: if !ok { log.Println("watcher.Events is not ok") return } // 特定のファイルへイベントが発生した場合 if event.Name == "tmp/target.txt" { log.Println("Event: ", event) } else { log.Println("not target file", event.Name) } case err, ok := <-watcher.Errors: if !ok { log.Println("watcher.Errors is not ok") return } log.Println("error:", err) } } }() err = watcher.Add("./tmp") if err != nil { log.Fatal(err) } <-make(chan struct{}) }
case event, ok := <-watcher.Events:
でwatcher.Eventsのchannelからのメッセージを受信した際の処理で、eventを受けとるので、ここからevent.Nameをチェックしています。
といった感じで指定したファイルへの変更イベントを拾うことができました。