Skip to content

ereyes01/firebase

Repository files navigation

Go Firebase

NOTE: This repo is in maintenance mode. If you're developing a new application, you should take a look at Google's official Firebase bindings. As of June 2020, this code is still stable and being used in production for real products. Maintenance / bug fixing will still be done if any is needed.

Helper library for invoking the Firebase REST API from your Go program. Supports the following operations:

  • Read and write values using Firebase's REST API operations
  • Stream updates to a Firebase path via the SSE / Event Source protocol
  • Use native Go types/structs in all Firebase operations
  • Server-side timestamps that are automatically converted into native Go times
  • Read and modify security rules

My starting point was the great work of cosn and JustinTulloss. Most of the code has since been refactored, and comprehensive unit tests that do not call out to the network have been added. Also, support for streaming via SSE / Event Source from Firebase has been added.

Please star on Github if you find this library useful! Thanks!

Build Status

Circle CI

Reference Documentation

GoDoc

Installation

  • Setup your GOPATH and workspace. If you are new to Go and you're not sure how to do this, read How to Write Go Code.
  • Dowload the package:
go get -u -t github.com/ereyes01/firebase

Run the Tests

  • To run the tests:
go test -race github.com/ereyes01/firebase

Usage

The usage examples below will use the sample Dinosaur Facts Firebase used in the REST tutorial

client := firebase.NewClient("https://dinosaur-facts.firebaseio.com", "", nil)

Suppose we have a struct defined that matches each entry in the dinosaurs/ path of this firebase. Our struct might be declared as follows:

type Dinosaur struct {
	Appeared int
	Height   float64
	Length   float64
	Order    string
	Vanished int
	Weight   float64
}

We could retrieve the lambeosarus record as follows:

var dino Dinosaur

err := client.Child("dinosaurs/lambeosaurus").Value(&dino)

We could query dinosaurs whose scores are greater than 50 as follows:

dinoScores := make(map[string]int)

err := client.Child("scores").OrderBy("$value").StartAt(50).Value(&dinoScores)

If I wanted to create a new dinosaur score (NOTE: the permissions of this firebase do not allow this), we could try:

value, err := client.Child("scores").Set("velociraptor", 500, nil)

We of course, don't have permissions to write to this Firebase. The error you'd get back should be:

Permission denied

Create your own free test Firebase and feel free to experiment with writing values!

Now suppose we wanted to watch changes to the Triceratops dinosaur in real-time. This, of course, will be a boring example because Triceratops will probably never change. However, this sample demonstrates how you would stream changes to a Firebase path in real-time (and stops streaming after 10 seconds):

    stop := make(chan bool)
	go func() {
		<-time.After(10 * time.Second)
		close(stop)
	}()

    // this helps convert incoming events into Dinosaur objects
    dinoParser := func(path string, data []byte) (interface{}, error) {
		var dino *Dinosaur
		err := json.Unmarshal(data, &dino)
		return dino, err
	}

	events, err := client.Child("dinosaurs/triceratops").Watch(dinoParser, stop)
	if err != nil {
		log.Fatal(err)
	}

	for event := range events {
		if event.Error != nil {
			log.Println("Stream error:", event.Error)
            continue
		}

		if event.UnmarshallerError != nil {
			log.Println("Malformed event:" event.UnmarshallerError)
            continue
		}

		newTriceratops := event.Resource.(*Dinosaur)
	}

The code above will yield a stream of Go Dinosaur objects (or rather, pointers to them). The magic is in the dinoParser callback. This function (passed to Watch) tells the watcher how to parse the json payload of the incoming events- in this case as Dinosaur pointers. When the streaming connection is closed, the events channel also closes.

When you watch a Firebase location, you'll get back an initial event showing the state of the location as it was when you started watching it. Thereafter, you will receive an event when a change happens that matches your criteria, or when some place in the location stopped matching your criteria. This can be a little confusing at first, especially when you combine queries with watching resources. It's just the way Firebase watching of resources works.

You can read more about this behavior in my Stack Overflow question and the subsequent discussion with one of the Firebase dudes.

Please see the Godoc reference for a guide to the code and a more detailed list of operations. Also, please familiarize yourself with Firebase's REST API capabilities before trying anything with this library.

Please open issues for any bugs or suggestions you may have, or send me a PR. Thanks!

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •