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:
mkdir crud-app && cd crud-app
Next we will initialize the go module and install the dependencies:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
go run main.go
Now we can use the following CURL commands to test each of the endpoints.
Create a memo:
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:
curl http://localhost:8000/memos
Get a memo by it's ID:
curl http://localhost:8000/memos/1
Update a memo:
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:
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.
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