How to do it...

These steps cover writing and running your application:

  1. From your Terminal or console application, create a new directory called ~/projects/go-programming-cookbook/chapter13/firebase and navigate to it.
  2. Run the following command:
$ go mod init github.com/PacktPublishing/Go-Programming-Cookbook-Second-Edition/chapter13/firebase

You should see a file called go.mod that contains the following content:

module github.com/PacktPublishing/Go-Programming-Cookbook-Second-Edition/chapter13/firebase
  1. Create a file called client.go with the following content:
package firebase

import (
"context"

"cloud.google.com/go/firestore"
"github.com/pkg/errors"
)

// Client Interface for mocking
type Client interface {
Get(ctx context.Context, key string) (interface{}, error)
Set(ctx context.Context, key string, value interface{}) error
Close() error
}

// firestore.Client implements Close()
// we create Get and Set
type firebaseClient struct {
*firestore.Client
collection string
}

func (f *firebaseClient) Get(ctx context.Context, key string) (interface{}, error) {
data, err := f.Collection(f.collection).Doc(key).Get(ctx)
if err != nil {
return nil, errors.Wrap(err, "get failed")
}
return data.Data(), nil
}

func (f *firebaseClient) Set(ctx context.Context, key string, value interface{}) error {
set := make(map[string]interface{})
set[key] = value
_, err := f.Collection(f.collection).Doc(key).Set(ctx, set)
return errors.Wrap(err, "set failed")
}
  1. Create a file called auth.go with the following content:
package firebase

import (
"context"

firebase "firebase.google.com/go"
"github.com/pkg/errors"
"google.golang.org/api/option"
)

// Authenticate grabs oauth scopes using a generated
// service_account.json file from
// https://console.firebase.google.com/project/go-cookbook/settings/serviceaccounts/adminsdk
func Authenticate(ctx context.Context, collection string) (Client, error) {

opt := option.WithCredentialsFile("/tmp/service_account.json")
app, err := firebase.NewApp(ctx, nil, opt)
if err != nil {
return nil, errors.Wrap(err, "error initializing app")
}

client, err := app.Firestore(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to intialize filestore")
}
return &firebaseClient{Client: client, collection: collection}, nil
}
  1. Create a new directory named example and navigate to it.
  2. Create a file named main.go with the following content:
package main

import (
"context"
"fmt"
"log"

"github.com/PacktPublishing/Go-Programming-Cookbook-Second-Edition/chapter13/firebase"
)

func main() {
ctx := context.Background()
c, err := firebase.Authenticate(ctx, "collection")
if err != nil {
log.Fatalf("error initializing client: %v", err)
}
defer c.Close()

if err := c.Set(ctx, "key", []string{"val1", "val2"}); err != nil {
log.Fatalf(err.Error())
}

res, err := c.Get(ctx, "key")
if err != nil {
log.Fatalf(err.Error())
}
fmt.Println(res)

if err := c.Set(ctx, "key2", []string{"val3", "val4"}); err != nil {
log.Fatalf(err.Error())
}

res, err = c.Get(ctx, "key2")
if err != nil {
log.Fatalf(err.Error())
}
fmt.Println(res)
}
  1. Run go run main.go.
  2. You may also run go build ./example. You should see the following output:
$ go run main.go 
[val1 val2]
[val3 val4]
  1. The go.mod file may be updated and the go.sum file should now be present in the top-level recipe directory.
  2. If you copied or wrote your own tests, go up one directory and run go test. Ensure that all the tests pass.