In this article, i am going to connect our Golang API with a Firestore database replacing the array that we are currently using to store the data. Firestore is a NoSQL database from Google Firebase…
Create Firestore Database
We have to go to console.firebase.google.com
and we go to create project and we assign a name to it “pragmatic-reviews” … we click on Continue button and we need to disable analytics on the project. Then we are going to click on Create Project button and this is going to take a while … then project is ready.

And we need to go to Database menu and here where it says Cloud Firestore, we click on Create database button. We are going to start in production mode and click on Next.

We can select the default location in this case is US Central but you can select another region or another location for the deployment of the database.

Click on Done button to finalizing the Firestore database creation, and now that the database is ready and we can start a collection for example we can assign a name to it in our case is going to be posts and this the structure that we are going to use we gonna have an ID as number, a Title as string, a Text as string.

We can Save this and we have our first document created… remember that Firebase is a NoSQL database where basically a database is a collection, and collection has multiple documents.

Prepare Private Key to access database
Next step we need to export a JSON file (with the private key to access…) so we can access the database. We need to go to Project Overview and click on Project Settings , and go to Service accounts tab, then click on Generate new private key button. and finally click on Generate key to download the JSON file.

Let’s open it and basically it’s going to include a project identifier that we are going to use this identifier in our code to access this database.

Once we have the JSON file, one of the recommended options to setup the access to the Firestore database and the Firebase services is creating this environment variable GOOGLE_APPLICATION_CREDENTIALS and this variable needs to point to the JSON file that we just downloaded. This will allow us to access the Firebase resources, in our case we are going to access the Firestore database.
$ sudo nano ~/.profile

Golang works with Firestore database
In the first article of the series we’ve been working on an initial version of our API using Mux and we were basically storing these post elements which structure is defined in file route.go, and within this posts array. In this article, we will show you how to store the posts on Firestore database using Golang.
We need to download the dependency and then you can import it in Golang code later.
$ go get cloud.google.com/go/firestore
We need to restructure our project by create more 2 folders entity and repository and place Golang code accordingly.
The bellow is the code of entity/post.go
package entity
type Post struct {
ID int64 `json:"id"`
Title string `json:"title"`
Text string `json:"text"`
}
The bellow is the code of repository/posts-repo.go
package repository
import (
"context"
"golang-rest-api/entity"
"log"
"cloud.google.com/go/firestore"
"google.golang.org/api/iterator"
)
type PostRepository interface {
Save(post *entity.Post) (*entity.Post, error)
FindAll() ([]entity.Post, error)
}
type repo struct{}
// NewPostRepository
func NewPostRepository() PostRepository {
return &repo{}
}
const (
projectId string = "pragmatic-reviews-62551"
collectionName string = "posts"
)
func (*repo) Save(post *entity.Post) (*entity.Post, error) {
ctx := context.Background()
client, err := firestore.NewClient(ctx, projectId)
if err != nil {
log.Fatalf("Failed to create a Firestore Client: %v", err)
return nil, err
}
defer client.Close()
_, _, err = client.Collection(collectionName).Add(ctx, map[string]interface{}{
"ID": post.ID,
"Title": post.Title,
"Text": post.Text,
})
if err != nil {
log.Fatalf("Failed adding a new post: %v", err)
return nil, err
}
return post, nil
}
func (*repo) FindAll() ([]entity.Post, error) {
ctx := context.Background()
client, err := firestore.NewClient(ctx, projectId)
if err != nil {
log.Fatalf("Failed to create a Firestore Client: %v", err)
return nil, err
}
defer client.Close()
var posts []entity.Post
iter := client.Collection(collectionName).Documents(ctx)
for {
doc, err := iter.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatalf("Failed to iterate the list of posts: %v", err)
}
post := entity.Post{
ID: doc.Data()["ID"].(int64),
Title: doc.Data()["Title"].(string),
Text: doc.Data()["Text"].(string),
}
posts = append(posts, post)
}
return posts, nil
}
And we need to make something changes on the file route.go for working with Firestore database correctly
package main
import (
"encoding/json"
"golang-mux-api/entity"
"golang-mux-api/repository"
"math/rand"
"net/http"
)
var (
repo repository.PostRepository = repository.NewPostRepository()
)
func getPosts(response http.ResponseWriter, request *http.Request) {
response.Header().Set("Content-type", "application/json")
posts, err := repo.FindAll()
if err != nil {
response.WriteHeader(http.StatusInternalServerError)
response.Write([]byte(`{"error": "Error getting the posts"}`))
}
response.WriteHeader(http.StatusOK)
json.NewEncoder(response).Encode(posts)
}
func addPost(response http.ResponseWriter, request *http.Request) {
response.Header().Set("Content-type", "application/json")
var post entity.Post
err := json.NewDecoder(request.Body).Decode(&post)
if err != nil {
response.WriteHeader(http.StatusInternalServerError)
response.Write([]byte(`{"error": "Error unmarshalling data"}`))
return
}
post.ID = rand.Int63()
repo.Save(&post)
response.WriteHeader(http.StatusOK)
json.NewEncoder(response).Encode(post)
}
Run and test new REST API
Start our REST API
$ go build
$ go run .
Let’s create more Post
$ curl -v --location 'http://localhost:8000/posts' --header 'Content-Type: application/json' --data '{
"title": "Title 2",
"text": "Text 2"
}'
Then get all posts
$ curl -v --location 'http://localhost:8000/posts'
Check on Cloud Firestore console

Download Source Code
$ git clone https://github.com/favtuts/golang-mux-api.git
$ cd golang-mux-api$ git checkout firestore
$ go build$ go run .