Creating a CRUD App With Go
Tags: go, beginners, crud, tutorial
Published: 2024-06-24 06:51:51

## Introduction

Hello! 😎

In this tutorial I will show you how to build a CRUD app using the Go programming language. By the end, you'll have a fully functioning CRUD (Create, Read, Update, Delete) app running locally. Let's get started.

---

## Requirements

- Go installed
- Basic understanding of Go

---

## Setting up the project

Create a new directory for the project and navigate into it:

```bash
mkdir crud-app && cd crud-app
```

Next we will initialize the go module and install the dependencies:

```bash
go mod init go-crud-app
go get -u github.com/gorilla/mux
```

Now that the project and required packages are installed we can start working on the application. 😸

---

## Coding the Application

Create a new file called "main.go" and import the following:

```go
package main

import (
    "encoding/json"
    "log"
    "net/http"
    "strconv"
    "github.com/gorilla/mux"
)
```

- encoding/json: For encoding and decoding JSON data
- log: For logging errors
- net/http: For building the HTTP server
- strconv: For converting strings to integers
- github.com/gorilla/mux: A popular package for routing HTTP requests

Next we define our global variables like so:

```go
var memos []Memo
var idCounter int
```

- memos: A slice that will store all our memos
- idCounter: A counter to keep track of memo IDs

Now we need to create a struct to define a memo:

```go
type Memo struct {
    ID      int    `json:"id"`
    Title   string `json:"title"`
    Content string `json:"content"`
}
```

Next we will create handlers for each of the CRUD operations, the first one will handle create a new memo:

```go
func createMemo(w http.ResponseWriter, r *http.Request) {
    var memo Memo
    json.NewDecoder(r.Body).Decode(&memo)
    idCounter++
    memo.ID = idCounter
    memos = append(memos, memo)
    json.NewEncoder(w).Encode(memo)
}
```

- Decode the JSON request body into a memo struct
- Increment the idCounter and assign a new memo
- Append the new memo to the memos slice
- Encode and return the created memo as a JSON response

The next function will handle getting all the memos:

```go
func getMemos(w http.ResponseWriter, r *http.Request) {
    json.NewEncoder(w).Encode(memos)
}
```

- Encode and return the memos slice as a JSON response

Below is the handler to handle getting a single memo:

```go
func getMemo(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)
    id, _ := strconv.Atoi(params["id"])

    for _, memo := range memos {
        if memo.ID == id {
            json.NewEncoder(w).Encode(memo)
            return
        }
    }

    http.Error(w, "Memo not found", http.StatusNotFound)
}
```

- Retrieve the id from the URL parameters
- Search for the memo with the matching ID in the memos slice
- Return the memo if found, otherwise returns a 404 error

The next function handles updating a memo:

```go
func updateMemo(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)
    id, _ := strconv.Atoi(params["id"])
    
    for i, memo := range memos {
        if memo.ID == id {
            json.NewDecoder(r.Body).Decode(&memo)
            memo.ID = id
            memos[i] = memo
            json.NewEncoder(w).Encode(memo)
            return
        }
    }

    http.Error(w, "Memo not found", http.StatusNotFound)
}
```

- Retrieve the id from the URL parameters
- Search for the memo with the matching ID in the memos slice
- Decode the JSON request body into the found memo and update it
- Return the updated memo as a JSON response or return a 404 error if not found

Lastly we need a function to handle the delete operation:

```go
func deleteMemo(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)
    id, _ := strconv.Atoi(params["id"])

    for i, memo := range memos {
        if memo.ID == id {
            memos = append(memos[:i], memos[i+1:]...)
            json.NewEncoder(w).Encode("The memo was deleted successfully")
            return
        }
    }

    http.Error(w, "Memo not found", http.StatusNotFound)
}
```

- Retrieve the id from the URL parameters
- Search for the memo with the matching ID in the memos slice
- Delete the memo by removing it from the slice
- Return a success message or a 404 error if the memo is not found

Next we need to set up the routes to handle each of the CRUD requests:

```go
func initializeRouter() {
    router := mux.NewRouter()

    router.HandleFunc("/memos", createMemo).Methods("POST")
    router.HandleFunc("/memos", getMemos).Methods("GET")
    router.HandleFunc("/memos/{id}", getMemo).Methods("GET")
    router.HandleFunc("/memos/{id}", updateMemo).Methods("PUT")
    router.HandleFunc("/memos/{id}", deleteMemo).Methods("DELETE")

    log.Fatal(http.ListenAndServe(":8000", router))
}
```

- Initialize a new router using mux.NewRouter
- Define routes for each CRUD operation and map them to the respective handlers
- Start the HTTP server on port 8000

Finally we need to implement the main function, as so:

```go
func main() {
    memos = append(memos, Memo{ID: 1, Title: "First memo", Content: "Hello World"})
    idCounter = 1
    initializeRouter()
}
```

- Initialize the memos slice with a sample memo
- Set the idCounter to 1
- Call the previous initializeRouter function to start the server

Done! Now we can move onto testing the application. 😆

---

## Testing the Application

First we need to start the server before we can make requests to it, this is done via the following command:

```bash
go run main.go
```

Now we can use the following CURL commands to test each of the endpoints.

Create a memo:
```bash
curl -X POST -d '{"title":"New Memo","content":"This is a new memo."}' -H "Content-Type: application/json" http://localhost:8000/memos
```

Get all memos:
```bash
curl http://localhost:8000/memos
```

Get a memo by it's ID:
```bash
curl http://localhost:8000/memos/1
```

Update a memo:
```bash
curl -X PUT -d '{"title":"Updated Memo","content":"This is an updated memo."}' -H "Content-Type: application/json" http://localhost:8000/memos/1
```

Delete a memo:
```bash
curl -X DELETE http://localhost:8000/memos/1
```

Feel free to change the contents and have a play around with it. 👀

---

## Conclusion

In this tutorial I have shown how to implement a CRUD application using the Go programming language, I'm having a lot of fun learning Go and I hope this tutorial has helped you.

As always you can find the sample code on my Github:
https://github.com/ethand91/go-crud

Happy Coding! 😎

---

Like my work? I post about a variety of topics, if you would like to see more please like and follow me.
Also I love coffee. 

[![“Buy Me A Coffee”](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/ethand9999)

If you are looking to learn Algorithm Patterns to ace the coding interview I recommend the [following course](https://algolab.so/p/algorithms-and-data-structure-video-course?affcode=1413380_bzrepgch