Monitoring file changes is a common task in many applications, whether it’s to trigger actions when files are updated or to keep track of changes in a folder. In this post, we’ll explore how to use the fsnotify library in Go to monitor a folder for file changes, such as file creation, modification, and deletion. We’ll focus on the benefits of its push mechanism, which allows for efficient notifications of changes without the need for constant polling.
Benefits of the Push Mechanism
The push mechanism, as used by fsnotify, offers several advantages over traditional polling methods:
- Improved efficiency: With push notifications, your application receives updates only when actual changes occur. This means fewer system resources are consumed, as your application doesn’t have to constantly check for changes.
- Faster response times: Since your application is immediately notified when changes occur, it can react faster to events, leading to more responsive applications.
- Reduced complexity: Using a push mechanism simplifies your application’s logic, as you don’t have to implement a polling loop or manage timers.
Example
Here’s a simple example of using fsnotify to monitor a folder for file changes:
package main
import (
"fmt"
"log"
"github.com/fsnotify/fsnotify"
)
var (
moitoredPath = "./monitored_folder"
)
func main() {
// Create a new fsnotify watcher.
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
}
// Check the type of event and log the details.
fmt.Printf("event: %v\n", event)
if event.Op&fsnotify.Write == fsnotify.Write {
fmt.Printf("modified file: %s\n", event.Name)
} else if event.Op&fsnotify.Create == fsnotify.Create {
fmt.Printf("created file: %s\n", event.Name)
} else if event.Op&fsnotify.Remove == fsnotify.Remove {
fmt.Printf("deleted file: %s\n", event.Name)
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Println("error:", err)
}
}
}()
// Watch a specific folder for changes.
err = watcher.Add(moitoredPath)
if err != nil {
log.Fatal(err)
}
<-done
}
Replace ./monitored_folder
with the path to the folder you want to monitor.
This example creates an fsnotify watcher and sets up a goroutine to listen for file system events. When an event occurs, the type of event and the affected file’s name are logged.
Please check official documentation of fsnotify to see more details about operations that are emitted by this package:
// The operations fsnotify can trigger; see the documentation on
// [Watcher] for a full description, and check them with [Event.Has].
const (
Create Op = 1 << iota
Write
Remove
Rename
Chmod
)

Conclusion
The fsnotify library makes it easy to monitor file changes in a folder using a push mechanism. This approach offers several benefits, such as improved efficiency, faster response times, and reduced complexity. However, it’s important to note that fsnotify might behave differently on different platforms due to OS-specific implementations of file system notifications. Always test your application on the target platform to ensure it works as expected.
If you enjoy reading medium articles and are interested in becoming a member, I would be happy to share my referral link with you!