Rest API with Golang and Cassandra DB
Published: 2022-01-12 11:02:36

Apache Cassandra is a highly scalable, high-performance distributed database designed to handle large amounts of data across many commodity servers, providing high availability with no single point of failure. It is a type of NoSQL database.

In this post we'll be creating a REST API form Golang and Cassandra DB.


Firsly I'll outline of this blog.

1. Create a keyspace of Cassandra (Similar to Database in MySQL)

2. Create a table inside the keyspace 

3. Connect with go-cql connector 

4. Create the rest-api


NOTE: This blog is being written according to an ubuntu system so there may be some minute changes according to your OS.



**1. Create a keyspace of Cassandra**


```
CREATE KEYSPACE users
WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 1};
```

A replication factor of one means that there is only one copy of each row in the Cassandra cluster. A replication factor of two means there are two copies of each row, where each copy is on a different node.

The details of these terms are not the focus of this blog thus I will explain in it in some later blogs.

**2. Create a table inside the keyspace**

```
use users;

CREATE TABLE stu(
   username text PRIMARY KEY,
   email text
   );
```


**TIME FOR SOME GOLANG !!!**



Firstly we'll create a main.go file and inside it we'll create a struct to map with the database structure 

```
type Student struct {
	Username string `json:"username"`
	Email    string `json:"email"`
}

```

For connecting with the cassandra we'll use gocql package and link of it is given below.

[github.com/gocql/gocql](url)


Now we will create our main function and start the server

```
func main() {
	http.HandleFunc("/", handleRequest)
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal(err)
	}
	fmt.Println("Server has Started")

}
```

For our cassandra client we'll create a new struct named Client which will have a pointer to gocql.Session which has all the required functionalities to interact with the database.

```
type Client struct {
	cassandra *gocql.Session
}

var cassandraClient *Client

```

**The IniitalizeDB() function**

This function is responsible for creating a connection between cassandra and Go and returning a *Client type variable

```
func InitializeDB() *Client {
	cluster := gocql.NewCluster("127.0.0.1")
	cluster.Consistency = gocql.Quorum
	cluster.Keyspace = "users"
	session, _ := cluster.CreateSession()
	fmt.Println("********************** Cassandra Initialized")
	return &Client{cassandra: session}
}
```


Now we call the InitializeDb() in the main function and pass the cassandraClient in a variable.

```
cassandraClient = InitializeDB();
```

Now we map the request to functions according to the POST, GET, PUT, DELETE


```
func handleRequest(w http.ResponseWriter, r *http.Request) {
	switch true {
	case r.Method == "POST":
		createStudent(w, r)
	case r.Method == "GET":
		getStudent(w, r)
	case r.Method == "PUT":
		updateStudent(w, r)
	case r.Method == "DELETE":
		deleteStudent(w, r)
	}

}
```


Atlast all the setup is done now we create the CRUD operations:


**1. CreateStudent function**
 
We have 2 functions firstly createStudent function which takes in the post request and routes it CreateStudent function which does the database query.

to Insert into cassandra we use the query.

**INSERT INTO users (username, email) VALUES(?,?)** and then add in the values.

the functions are below.

```
func createStudent(w http.ResponseWriter, r *http.Request) {
	var NewUser Student
	reqBody, err := ioutil.ReadAll(r.Body)
	if err != nil {
		fmt.Fprintf(w, "wrong data")
	}
	json.Unmarshal(reqBody, &NewUser)
	//Call the DB
	err = cassandraClient.CreateStudent(NewUser)
	if err != nil {
		panic(err)
	}
	fmt.Println(NewUser)

}



func (s *Client) CreateStudent(stu Student) error {
	err := s.cassandra.Query("INSERT INTO users (username, email) VALUES(?,?)", stu.Username, stu.Email).Exec()
	if err != nil {
		return err
	}

	return nil
}

```


Similarly for the other methods


**2. Update Student**

**UPDATE users SET email=? WHERE username=?**

```

func updateStudent(w http.ResponseWriter, r *http.Request) {
	var UpdateStu Student
	reqBody, err := ioutil.ReadAll(r.Body)
	if err != nil {
		fmt.Fprintf(w, "Kindly enter data properly")
	}
	json.Unmarshal(reqBody, &UpdateStu)
	//DB Call
	err = cassandraClient.UpdateStudent(UpdateStu)
	if err != nil {
		panic(err)
	}
	fmt.Println(UpdateStu)

}



func (s *Client) UpdateStudent(stu Student) error {
	err := s.cassandra.Query("UPDATE users SET email=? WHERE username=?", stu.Email, stu.Username).Exec()
	if err != nil {
		return err
	}
	return nil
}


```


**3. Get Student**

**SELECT * FROM users WHERE username=?**



```
func getStudent(w http.ResponseWriter, r *http.Request) {
	name := r.URL.Query().Get("username")
	//DB call
	stu, err := cassandraClient.GetStudent(name)
	if err != nil {
		panic(err)
	}
	fmt.Println(stu)
}

func (s *Client) GetStudent(username string) (Student, error) {

	stu := Student{}
	ctx := context.Background()
	err := s.cassandra.Query("SELECT * FROM users WHERE username=?", username).WithContext(ctx).Consistency(gocql.One).Scan(&stu.Username, &stu.Email)
	if err != nil {
		return stu, err
	}
	return stu, nil
}


```


**4. Delete Student**


```
func deleteStudent(w http.ResponseWriter, r *http.Request) {
	name := r.URL.Query().Get("username")
	//Db Call
	err := cassandraClient.DeleteStudent(name)
	if err != nil {
		panic(err)
	}
	fmt.Println("Successfully Deleted")

}


func (s *Client) DeleteStudent(name string) error {
	err := s.cassandra.Query("DELETE FROM users WHERE username=?", name).Exec()
	if err != nil {
		return err
	}
	return nil
}


```



So now if you want to access the whole code here is the link 
https://github.com/mrshukla1805/golang-cassandra

Please do provide a star on the repository!!



Enjoy and keep learning ;)