Hi Eddy,
I'm a long-time fan of Go and I love seeing people make Firebase more approachable in Go. At some point I might get to a 1st party library with caching and all the other subtle things our clients handle for you. I love that your library works well with marshalers too--far too few libraries handle strongly typed models.
Out of curiosity, what are the params in Push/Set/Update/Remove/Rules/SetRules? There are a few cases where I see boolean parameters or nil values. In these cases I personally prefer to use a parameter struct or provide multiple functions. This lets developers omit params that are often unneeded and makes code self-documenting when they're provided.
Like you, my first approaches at the Watch function also used channels. The "Go Way" is to not expose channels (the only library I can think of that violates this is time.Timer), but I struggled to do any better. Your clever EventUnmarshaller gave me an idea though: what if the return type for Watch was an object with a Cancel() function and a json.Decoder (which
supports multiple JSON docs)? Then the developer wouldn't need to ever type interface{} and there are no dangling channels. You'd use it like
func DoSomethingSillyWithProfile(profile string, timesToDoSomethingSilly int) error {
watcher, err := root.Child('profiles').Child(profile).Watch();
if err != nil {
return err;
}
updatesPublished := 0
for {
if updatesPublished > timesToDoSomethingSilly {
return watcher.Stop()
}
var profile Profile
if err := watcher.Decode(&profile); err != nil {
return err
}
doSomethingSilly(profile)
updatesPublished++
}
}
All in all, this is really cool. Thanks for contributing to the community!
--Thomas