When using the template package one doesn’t want to read the templates from the file system every time they are used. Likewise you want to restart the process just to test some minor change within the template.
Go’s os/inotify package creates a file watcher, but it only supports Linux, and in the spirit of keeping my Go app portable I’ve created a simple File Poller.
The code is on github.com/hokapoka/fspoll and can be installed via goinstall :
goinstall github.com/hokapoka/fspoll
Here are the Exported methods :
- NewFilePoller(timeout) *FilePoller
NewFilePollercreates a pointer to a new FilePoller. Thetimeoutargument defines how frequently the poller will check the files- func(*FilePoller) Add(name) os.Error
Addmethod of the FilePoller will add the file, located atname, to the poller.- func(*FilePoller) Get(name) (bytes.Buffer, bool, os.Error)
Getrecivies the filename as an argument and has 3 return valuesbytes.Buffercontains the current contents of the fileboolindicates that it has changed since the previousGetos.Errorreturns an error if the poller recivied an error when reading the given file.
There’s a simple example within the README on github
Any feedback, or suggestion on how to better implement it are very welcome.
The problem with that interface, as I see it, is that it provides no way for the user of the package to find out when any changes have occurred. The caller would have to do its own polling, which seems wrong. Another problem is that the caller does not necessarily want to keep the entire file contents in memory – there’s no real need to do so AFAICS.
Here’s a possible alternative API:
type Poller struct {
}
// NewPoller creates a new Poller object that checks
// files every interval nanoseconds, and sends the names
// of any files that might have changed on c.
func NewPoller(interval int64) (p *Poller, c <-chan string)
// Add adds a file to the Poller. It is an error if the
// file has already been added or if it does not exist.
func (p *Poller) Add(name string) os.Error
// Remove removes a file from the Poller.
func (p *Poller) Remove(name string)
I agree with rog. In fact, taking into account there is no way to know if a file was modified until you call Get, there is no need to poll at all. To have the same result you have now, you could just have a Modified(name string) bool function which keeps the last time in a map and checks if the file has been updated from the last call. Then, it would be easy to implement a real poller with the interface that rog suggested on top of that.
I handle the template update problem by creating a wrapper around templates. In production mode, the wrapper loads the template when the wrapper is created. In debug mode, the wrapper loads the template every time the template is executed.
Really handy!