Introduction
Golang has become very popular nowadays. It’s fast, has an easy-to-learn syntax, and is gaining ground among backend developers. Today, we will learn how to use Golang to perform Create, Read, Update, and Delete (CRUD) operations against an equally popular database, Fauna.
Fauna is a flexible, developer-friendly, transactional cloud database delivered as a secure Data API that provides two interfaces: GraphQL and the Fauna Query Language (FQL). Fauna is a unique indexed document system that supports relations, documents, and graphs for unmatched modeling flexibility. It includes functionality to store collections, indexes, and other databases (multi-tenancy). To learn more about Fauna, visit the official documentation. Fauna uses a pre-existing infrastructure to build web applications without usually setting up a custom API server. This efficiently helps to save time for developers, and the stress of choosing regions and configuring storage that exists among other databases. All maintenance we need is actively taken care of by engineers and automated DevOps at Fauna.
Here’s the full code of the project we would build in this tutorial. And throughout the tutorial, we’ll modularize the different API routes defined within the project. This will help us test out the different API request without it being dependent.
Initial setup
Let’s set up our development environment. First, we will need to install Golang because that is the language we will be using here. Click this link to learn how to install it for your operating system.
Next, we need to create an account on the Fauna either through the dashboard UI or through fauna-shell
CLI. For this tutorial, we’ll make use of the dashboard to setup and interact with our database. Follow this link to create an account. Then create your first database and navigate to the Security webpage by clicking on the Security link on the sidebar to generate an API key for our application. Fill the input field and click the SAVE
button.
N.B., make sure you take note of your connection string, especially the Secret API key, as it is only shown once. This secret won't be displayed again, so please copy and save it somewhere safe. This tutorial also assumes you have some knowledge of programming with Golang.
Next, let’s jump into building the different parts of our application.
Project overview
For the project, we’ll build the REST API that allows us to make API request to create, read, update, and delete items from the Fauna database. We’ll build a Blog-like platform, where we can create, retrieve, update and delete a post from the application. We’ll use Postman to make API requests to the server that we’ll setup up with Golang.
Setup Local Environment
Let’s start with creating our root folder within the Golang GOPATH
at the root directory of your local machine, $HOME/go/src/
. The default $GOPATH
on Unix is $HOME/go
. We'll store our programs there.
mkdir faunadb-go
cd faunadb-go
Now, let’s start with initializing and adding the go-modules required for our application by using the go get
command. Let install the Fauna’s open source Go driver, which provides the resources required to interact with Fauna, and also build the REST API using the **gorilla/mux**
router instead of the traditional **net/http**
router.
go get github.com/fauna/faunadb-go/v5/faunadb
go get github.com/gorilla/mux
Please note that the driver undergoes breaking changes from time to time. It is recommended to use one of the following methods instead:
JSON
For the purpose of this tutorial I’ll be using JavaScript Object Notation as a means of sending and receiving all information and thankfully Go comes with some excellent support for encoding and decoding these formats using the standard library package, encoding/json.
Marshalling
There’s a good support within Golang to easily convert data structures in GO into JSON by using something called marshalling which produces a byte slice containing a very long string with no extraneous white space.
Setup a server to handle HTTP requests
To setup a server using Golang, we’ll first create a new file called **main.go**
. Within this **main.go**
file we’ll want to define 3 different functions. A **homePage**
function that will handle all requests to our root URL, a **handleRequests**
function that will match the URL path hit with a defined function and a **main**
function which will act as the default entrance into our REST API.
package main
import (
"fmt"
"net/http"
f "github.com/fauna/faunadb-go/faunadb"
"github.com/gorilla/mux"
)
var client = f.NewFaunaClient(os.Getenv("FAUNADB_SECRET_KEY"))
// Create a class to store Blog
_, _ = client.Query(f.CreateCollection(f.Obj{"name": "Blog"}))
func homePage(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to REST API with FaunaDB")
fmt.Println("We've reached the Home page endpoint!")
}
func handleRequests() {
r := mux.NewRouter().StrictSlash(true)
r.HandleFunc("/", homePage)
log.Fatal(http.ListenAndServe(":10000", r))
}
func main() {
handleRequests()
}
Now, let run the Go program using the go run
command in the terminal as below:
go run main.go
Let’s open Postman to test that our server is actually listening for incoming requests. Now, make a GET request to the localhost:10000/ URL to hit call the homePage
function:
Create a Fauna collection instance
Here, we’ll create a route to create a collection on Fauna. Within this collection, we’ll create a Document. To create new documents in a Fauna collection, we’ll first make a connection to the database using the client provided by Fauna, then use the Create
method that allows us to insert a single document into our database. We named our Document Blog
in this tutorial
func createNewPost(w http.ResponseWriter, r *http.Request) {
req, _ := ioutil.ReadAll(r.Body)
var post Post
json.Unmarshal(req, &post)
// Save post at FaunaDB
newProfile, _ := client.Query(
f.Create(
f.Collection("Blog"),
f.Obj{"data": post},
),
)
// Get generated post ID
_ = newProfile.At(ref).Get(&postId)
Blog = append(Blog, post)
json.NewEncoder(w).Encode(post)
}
Next, let’s update the handleRequests
function, defining a new route to handle the createNewPost
function:
func handleRequests() {
r := mux.NewRouter().StrictSlash(true)
r.HandleFunc("/", homePage)
r.HandleFunc("/blog/post", createNewPost)
log.Fatal(http.ListenAndServe(":10000", r))
}
Let’s open Postman to test that our server is actually listening for incoming requests. Now, make a POST request to the localhost:10000/blog/post URL to hit call the createNewPost
function:
Next, let’s navigate to our database to confirm that our Document was successfully created on the database.
Retrieve a Document from Fauna collection instance
We’ll define a gorilla/mux
route which will allow us to easily do things such as retrieve path based on the current value of query parameter, var postId f.RefV
in this tutorial.
func getSinglePost(w http.ResponseWriter, r *http.Request) {
req, _ := ioutil.ReadAll(r.Body)
var post Post
json.Unmarshal(req, &post)
// Retrieve post by its ID
value, _ := client.Query(f.Get(postId))
_ = value.At(data).Get(&post)
json.NewEncoder(w).Encode(value)
}
In the above code, we’ll use the json
to parse the value
from the call of f.Get()
method as we pass in the postId
into it. Next, let’s update the handleRequests
function, defining a new route to handle the getSinglePost
function:
func handleRequests() {
r := mux.NewRouter().StrictSlash(true)
r.HandleFunc("/", homePage)
r.HandleFunc("/blog/post", createNewPost)
r.HandleFunc("/blog", getSinglePost).Methods("GET")
log.Fatal(http.ListenAndServe(":10000", r))
}
Let’s open Postman to test that our server is actually listening for incoming requests. Now, make a GET request to the localhost:10000/blog/post URL to hit call the getSinglePost
function:
Update a Document from Faunacollection instance
Fauna provides the f.Update
operation to change documents in a collection. f.Update
function changes the specified fields or overwrites existing data with new fields you provided in a document.
func updatePost(w http.ResponseWriter, r *http.Request) {
// Update existing post entry
_, _ = client.Query(
f.Update(
postId,
f.Obj{"data": f.Obj{
"Title": "Adieu to Fauna blog posts", "Content": "In the next article, we'll build a simple micro-service", "Summary": "This article featured Golang architectures",
}},
),
)
}
In the above code, we hardcoded our update using the f.Obj
, Obj
is a expression shortcut to represent any valid JSON object. Next, let’s update the handleRequests
function, defining a new route to handle the updatePost
function:
func handleRequests() {
r := mux.NewRouter().StrictSlash(true)
r.HandleFunc("/", homePage)
r.HandleFunc("/blog/post", createNewPost)
r.HandleFunc("/blog", getSinglePost).Methods("GET")
r.HandleFunc("/blog", updatePost).Methods("PUT")
log.Fatal(http.ListenAndServe(":10000", r))
}
Let’s open Postman to test that our server is actually listening for incoming requests. Now, make a GET request to the localhost:10000/blog/post URL to hit call the updatePost
function. Once we’ve made the API request through Postman, let’s navigate to our database to confirm that our Document was successfully updated on the database.
Delete a Document from Fauna collection instance
We’ll always at a point need to delete the data being exposed by your REST API. In order to do this, you need to expose a **DELETE**
endpoint within our API route that will make request to the database to delete whatever is associated with that identifier.
In this section of this tutorial, you are going to be creating another endpoint which receives **HTTP DELETE**
requests and deletes a post if they match the given ref
parameter.
func deletePost(w http.ResponseWriter, r *http.Request) {
// Delete post using its ID
_, _ = client.Query(f.Delete(postId))
}
With the f.Delete()
will delete a particular Document from the **Blog**
collection within our database. Next, let’s update the handleRequests
function, defining a new route to handle the deletePost
function:
func handleRequests() {
r := mux.NewRouter().StrictSlash(true)
r.HandleFunc("/", homePage)
r.HandleFunc("/blog", getSinglePost).Methods("GET")
r.HandleFunc("/blog/post", createNewPost)
r.HandleFunc("/blog", deletePost).Methods("DELETE")
r.HandleFunc("/blog", updatePost).Methods("PUT")
log.Fatal(http.ListenAndServe(":10000", r))
}
Now, let’s make a DELETE request to the localhost:10000/blog/post URL to hit call the updatePost
function on Postman. Once we’ve made the API request through Postman, let’s navigate to our database to confirm that our Document was successfully deleted from the database:
Now our COLLECTION on the database is empty as we have deleted all the posts from the database.
Conclusion
I hope this was helpful to guide you through what could be considered often to be a challenging task. The lack of straightforward resources on using Fauna with Go requires developers to spend a lot of time exploring documentation. With this article as a reference guide, you can confidently integrate Fauna into a Go application.
You can head over to the official Fauna and Go driver documentation to explore more functionalities that Fauna provides.
Top comments (0)