Store and sync data in Firebase with Golang

Here, I am going to describe how to store and sync data in Firebase with Golang. Aslo, I have explained the how to connect the Firebase with Golang and authenticate using two types of credentials, namely Json and OAuth. When I first tried this, I faced some issues during connectivity, and hence thought it would be good to consolidate the process into an article.

The Firebase Real time Database, by definition, is a cloud-hosted database. This Firebase NoSQL cloud database is trending as the new go-to data storage concept. With this, data is stored as JSON, and not in the traditional format. Also, Firebase performs real time data synchronisation to every client that is connected.

How does it work?

The Firebase Real time Database lets you build rich, collaborative applications by allowing secure access to the database directly from client-side code.

 

Since I am describing how to implement a client of Firebase with Golang, first, we need to install the Firego package, and the fireauth package for authentication. Below are the steps:

Installation


go get -u gopkg.in/zabawaba99/firego.v1

 

If you want to add authentication token (as mentioned above), install the fireauth package also

 


go get -u github.com/zabawaba99/fireauth

[code]

 

If you want to add OAuth authentication by means of JWT (JSON Web Token):

[code]

go get -u golang.org/x/oauth2

go get -u golang.org/x/oauth2/google

Usage

Next, in order to use Firebase, we need to access the installed packages, as below:

 

import firego

 


import(

 "gopkg.in/zabawaba99/firego.v1"

 

  //(If fireauth has been installed by you for authentication, issue the following command)

 

 _ "github.com/zabawaba99/fireauth"

//(If oAuth package has been installed by you for authentication, issue the following commands)

 

 _ "golang.org/x/oauth2"

 _ "golang.org/x/oauth2/google"

)

 

Next, we need to generate a new firego reference:

 


f := firego.New("https://test-sample-application.firebaseio.com", nil)

 

If we have an already existing http client, we can generate the reference as below:

 


f := firego.New("https://test-sample-application.firebaseio.com", client)

 

Request Timeouts

By default, the Firebase reference will timeout after 30 seconds of trying to reach a Firebase server. You can configure this value by setting the global timeout duration, as:

 


firego.TimeoutDuration = time.Minute

 

Auth Tokens

Now, in order to set the authentication for the Firebase, we need to get the token using fireauth package.

 

Get the secret key from under Project Settings. The url should looks something like:

 

“https://console.firebase.google.com/project/YOUR_PROJECT_NAME/settings/database” or “https://console.firebase.google.com/project/YOUR_PROJECT_NAME/settings/serviceaccounts/databasesecrets”

 


// Create a TokenGenerator

gen := fireauth.New("<SECRET-KEY>")

 

// Generate a token

data := fireauth.Data{"uid": "1"}

token, err := gen.CreateToken(data, nil)

if err != nil {

 // handle error

}

f.Auth(token)

 

If you don't want authentication:

 


// Unauth removes the current token being used to authenticate.

f.Unauth()

 

Are you going to use OAuth authentication?
Then, follow as below:

 


jsonKey, err := ioutil.ReadFile("./json-credentials.json") // or path of whatever name you downloaded the JWT to.

if err != nil {

 // handle err

}

conf, err := google.JWTConfigFromJSON(jsonKey, "https://www.googleapis.com/auth/userinfo.email",

"https://www.googleapis.com/auth/firebase.database")

if err != nil {

 // handle err

}

 

client := conf.Client(oauth2.NoContext)
fb := firego.New("https://my-sample-app.firebaseio.com", client)

 

Once the authentication is done, and all has been set, we can access the set database. Let us see them below:

 

Get Value

Get the values of the reference.

 


var v map[string]interface{}

if err := f.Value(&v); err != nil {

 // handle err

}

fmt.Printf("%s\n", v)

 

Querying

Take a look at Firebase's query parameters for more information on what each function does.

 


var v map[string]interface{}

if err := f.StartAt("a").EndAt("c").LimitToFirst(8).OrderBy("field").Value(&v); err != nil {

 // handle err

}

fmt.Printf("%s\n", v)

 

Set Value

Set the value of the reference.

 


v := map[string]string{"foo":"bar"}

if err := f.Set(v); err != nil {

 // handle err

}

 

Push Value

Push creates a reference to an auto-generated child location.

 


v := "bar"

pushedFirego, err := f.Push(v)

if err != nil {

 // handle err

}

 

var bar string

if err := pushedFirego.Value(&bar); err != nil {

 // handle err

}

 

// prints "https://my-sample-app.firebaseio.com/-JgvLHXszP4xS01CV-nI: bar"

fmt.Printf("%s: %s\n", pushedFirego, bar)

 

 

Update Child

Update the specific child with the given value.

 


v := map[string]string{"foo":"bar"}

if err := f.Update(v); err != nil {

 // handle err

}

 

Remove Value

Remove the reference from the cloud.

 


if err := f.Remove(); err != nil {

 // handle err

}

 

Watch a Node

The Watch function listens for any changes on an instance of the specified Firebase. The result is passed over to the given channel. Since only one connection can be established at any given time, f.StopWatching should be mandatorily issued before the next call to Watch. If not, the second or next call will result in the given channel being closed and nil being returned immediately.

 


event_notifications := make(chan firego.Event) //Here, we assign the channel to a variable

if err := f.Watch(event_notifications); err != nil {

 // handle err

}

 

defer f.StopWatching()

for event := range event_notifications {

 fmt.Printf("Event %#v\n", event)

}

fmt.Println("Notifications have stopped")

 

Change reference

You, by now, know that a reference is used to save or read data from a specified reference. Ref function returns a copy of an existing Firebase reference with a new path.

 


userID := "bar"

usersRef,err := f.Ref("users/"+userID)

if err != nil {

 // handle err

}

v := map[string]string{"id":userID}

if err := usersRef.Set(v); err != nil {

 // handle err

}

 

That’s it. We now have a basic idea as to how to implement a Firebase with Golang, and how to perform the basic operations on the same. As mentioned in the beginning, two options are given here for authentication on Firebase with Golang. It is simply a matter of choice.

The above example is given in detail here. You can try it out.

Also, you can check the GoDocs for more details.