Building a CRUD Application with Go

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Setup
  4. Creating a Simple CRUD Application
  5. Conclusion

Introduction

In this tutorial, we will learn how to build a CRUD (Create, Read, Update, Delete) application using Go. By the end of this tutorial, you will have a basic understanding of how to create a web application with Go and perform CRUD operations on a database.

Prerequisites

To follow along with this tutorial, you should have a basic understanding of the Go programming language, including variables, functions, and the Go syntax. Additionally, you should have Go installed on your machine.

Setup

Before we begin, let’s set up our development environment.

  1. Install Go: Visit the official Go website and follow the instructions to install Go for your specific operating system.

  2. Verify Installation: Open a terminal or command prompt and run the following command to verify that Go is installed correctly:

     go version
    

    If you see the version number, it means Go is installed successfully.

  3. Text Editor: Choose a text editor or an integrated development environment (IDE) to write your Go code. Some popular options include Visual Studio Code, Atom, and GoLand.

Creating a Simple CRUD Application

Step 1: Setting up the Project Structure

Let’s start by creating the necessary project structure for our CRUD application. Open your terminal or command prompt and execute the following commands:

mkdir crud-app
cd crud-app
mkdir templates

In the crud-app directory, create a new file called main.go and open it in your chosen text editor.

Step 2: Importing Required Packages

In the main.go file, import the necessary packages for our CRUD application:

package main

import (
    "fmt"
    "log"
    "net/http"
    "html/template"
    "github.com/gorilla/mux"
)

Here, we import the fmt package for console output, log for logging errors, net/http for creating an HTTP server, html/template for rendering HTML templates, and github.com/gorilla/mux for handling routing and URL parameters.

Step 3: Creating the Database Connection

Next, we will create a database connection using MongoDB as an example. Make sure you have MongoDB installed and running on your machine.

// Connection string for MongoDB
const connString = "mongodb://localhost:27017"

// Database name
const dbName = "crud-app-db"

// Collection name
const collectionName = "users"

// Creating a new MongoDB session
var session *mgo.Session

func init() {
    // Establish MongoDB session
    var err error
    session, err = mgo.Dial(connString)
    if err != nil {
        log.Fatal(err)
    }
    session.SetMode(mgo.Monotonic, true)
}

// Database connection handler
func getDB() *mgo.Database {
    return session.DB(dbName)
}

In this code, we define the connection string for MongoDB, the database name, and the collection name. We create a new session using the mgo.Dial method and set the session mode to mgo.Monotonic. Finally, we define a getDB function to retrieve the database for performing CRUD operations.

Step 4: Creating the User Struct and CRUD Handlers

Now, let’s define a User struct to represent our data model and create the necessary CRUD handlers.

// User struct
type User struct {
    ID       bson.ObjectId `bson:"_id,omitempty"`
    Name     string        `bson:"name"`
    Email    string        `bson:"email"`
    Password string        `bson:"password"`
}

// Create user
func createUser(w http.ResponseWriter, r *http.Request) {
    // Parse request body
    err := r.ParseForm()
    if err != nil {
        log.Println(err)
        http.Error(w, "Bad Request", http.StatusBadRequest)
        return
    }

    // Get form values
    name := r.Form.Get("name")
    email := r.Form.Get("email")
    password := r.Form.Get("password")

    // Validate form values
    if name == "" || email == "" || password == "" {
        http.Error(w, "Missing form fields", http.StatusBadRequest)
        return
    }

    // Create user object
    newUser := &User{
        ID:       bson.NewObjectId(),
        Name:     name,
        Email:    email,
        Password: password,
    }

    // Insert user into the database
    err = getDB().C(collectionName).Insert(newUser)
    if err != nil {
        log.Println(err)
        http.Error(w, "Internal Server Error", http.StatusInternalServerError)
        return
    }

    // Render success message
    fmt.Fprintf(w, "User successfully created!")
}

// Read user
func readUser(w http.ResponseWriter, r *http.Request) {
    // Get user ID from URL parameter
    vars := mux.Vars(r)
    userID := vars["id"]

    // Find user by ID
    result := User{}
    err := getDB().C(collectionName).FindId(bson.ObjectIdHex(userID)).One(&result)
    if err != nil {
        log.Println(err)
        http.Error(w, "User not found", http.StatusNotFound)
        return
    }

    // Render user details
    fmt.Fprintf(w, "User: %s, Email: %s", result.Name, result.Email)
}

// Update user
func updateUser(w http.ResponseWriter, r *http.Request) {
    // Get user ID from URL parameter
    vars := mux.Vars(r)
    userID := vars["id"]

    // Find user by ID
    result := User{}
    err := getDB().C(collectionName).FindId(bson.ObjectIdHex(userID)).One(&result)
    if err != nil {
        log.Println(err)
        http.Error(w, "User not found", http.StatusNotFound)
        return
    }

    // Parse request body
    err = r.ParseForm()
    if err != nil {
        log.Println(err)
        http.Error(w, "Bad Request", http.StatusBadRequest)
        return
    }

    // Update user details
    result.Name = r.Form.Get("name")
    result.Email = r.Form.Get("email")
    result.Password = r.Form.Get("password")

    // Save updated user to the database
    err = getDB().C(collectionName).UpdateId(result.ID, result)
    if err != nil {
        log.Println(err)
        http.Error(w, "Internal Server Error", http.StatusInternalServerError)
        return
    }

    // Render success message
    fmt.Fprintf(w, "User successfully updated!")
}

// Delete user
func deleteUser(w http.ResponseWriter, r *http.Request) {
    // Get user ID from URL parameter
    vars := mux.Vars(r)
    userID := vars["id"]

    // Delete user from the database
    err := getDB().C(collectionName).RemoveId(bson.ObjectIdHex(userID))
    if err != nil {
        log.Println(err)
        http.Error(w, "Internal Server Error", http.StatusInternalServerError)
        return
    }

    // Render success message
    fmt.Fprintf(w, "User successfully deleted!")
}

Here, we define our User struct with the necessary fields. We create handlers for creating a user, reading a user, updating a user, and deleting a user. These handlers perform the respective CRUD operations on the MongoDB database.

Step 5: Setting up Routing

To handle incoming requests and map them to the appropriate handlers, we will use the gorilla/mux package.

func setupRoutes() {
    // Create a new router
    router := mux.NewRouter().StrictSlash(true)

    // Set up route handlers
    router.HandleFunc("/users", createUser).Methods("POST")
    router.HandleFunc("/users/{id}", readUser).Methods("GET")
    router.HandleFunc("/users/{id}", updateUser).Methods("PUT")
    router.HandleFunc("/users/{id}", deleteUser).Methods("DELETE")

    // Start the server
    log.Fatal(http.ListenAndServe(":8080", router))
}

In this code, we create a new router using mux.NewRouter(). We define the route patterns for creating, reading, updating, and deleting a user. Finally, we start the HTTP server using http.ListenAndServe().

Step 6: Running the Application

To run the application, add the following code to the main function:

func main() {
    fmt.Println("Starting CRUD application...")
    setupRoutes()
}

Save the main.go file and return to your terminal or command prompt. Navigate to the crud-app directory and execute the following command:

go run main.go

Now, your CRUD application is up and running on http://localhost:8080. You can use tools like curl or any API testing tool to interact with the application.

Conclusion

In this tutorial, we have learned how to build a CRUD application using Go. We started by setting up the project structure, importing the required packages, and creating a database connection. Then, we defined the necessary CRUD handlers and set up routing using gorilla/mux. Finally, we ran the application and tested it using HTTP requests.

By understanding the concepts and code presented in this tutorial, you can now build your own CRUD applications using Go. Remember to explore and experiment with different databases, libraries, and frameworks to further enhance your Go web development skills. Happy coding!