This tutorial will guide you through creating a CRUD (Create, Read, Update, Delete) API using Golang and MongoDB. We'll test all the REST APIs using Postman.
Prerequisites
- Go installed on your machine (latest version).
- MongoDB installed and running.
- Postman for testing APIs.
Step 1: Set Up Your Go Project
-
Create a new directory for your project and navigate into it:
mkdir go-crud-api-mongodb cd go-crud-api-mongodb
-
Initialize a new Go module:
go mod init go-crud-api-mongodb
Step 2: Install Required Packages
Install the necessary packages for handling MongoDB and HTTP requests:
go get go.mongodb.org/mongo-driver/mongo
go get go.mongodb.org/mongo-driver/mongo/options
go get github.com/gorilla/mux
Step 3: Set Up the MongoDB Database
-
Start MongoDB and create a new database and collection:
use go_crud_api; db.createCollection("users");
Step 4: Create the Main Application File
Create a new file main.go
and set up the basic structure:
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"time"
"github.com/gorilla/mux"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
// User represents the model for our resource
type User struct {
ID primitive.ObjectID `json:"id,omitempty" bson:"_id,omitempty"`
Name string `json:"name,omitempty" bson:"name,omitempty"`
Email string `json:"email,omitempty" bson:"email,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty" bson:"created_at,omitempty"`
}
var client *mongo.Client
func main() {
// Initialize MongoDB client
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
client, _ = mongo.Connect(ctx, clientOptions)
router := mux.NewRouter()
router.HandleFunc("/users", getUsers).Methods("GET")
router.HandleFunc("/user/{id}", getUser).Methods("GET")
router.HandleFunc("/user", createUser).Methods("POST")
router.HandleFunc("/user/{id}", updateUser).Methods("PUT")
router.HandleFunc("/user/{id}", deleteUser).Methods("DELETE")
log.Fatal(http.ListenAndServe(":8000", router))
}
// getUsers fetches all users from the database
func getUsers(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var users []User
collection := client.Database("go_crud_api").Collection("users")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
cursor, err := collection.Find(ctx, bson.M{})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer cursor.Close(ctx)
for cursor.Next(ctx) {
var user User
cursor.Decode(&user)
users = append(users, user)
}
json.NewEncoder(w).Encode(users)
}
// getUser fetches a single user by ID from the database
func getUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
params := mux.Vars(r)
id, _ := primitive.ObjectIDFromHex(params["id"])
var user User
collection := client.Database("go_crud_api").Collection("users")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
err := collection.FindOne(ctx, bson.M{"_id": id}).Decode(&user)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
json.NewEncoder(w).Encode(user)
}
// createUser creates a new user in the database
func createUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var user User
_ = json.NewDecoder(r.Body).Decode(&user)
user.ID = primitive.NewObjectID()
user.CreatedAt = time.Now()
collection := client.Database("go_crud_api").Collection("users")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
_, err := collection.InsertOne(ctx, user)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
json.NewEncoder(w).Encode(user)
}
// updateUser updates an existing user in the database
func updateUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
params := mux.Vars(r)
id, _ := primitive.ObjectIDFromHex(params["id"])
var user User
_ = json.NewDecoder(r.Body).Decode(&user)
collection := client.Database("go_crud_api").Collection("users")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
update := bson.M{
"$set": user,
}
_, err := collection.UpdateOne(ctx, bson.M{"_id": id}, update)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
user.ID = id
json.NewEncoder(w).Encode(user)
}
// deleteUser deletes a user from the database
func deleteUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
params := mux.Vars(r)
id, _ := primitive.ObjectIDFromHex(params["id"])
collection := client.Database("go_crud_api").Collection("users")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
_, err := collection.DeleteOne(ctx, bson.M{"_id": id})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusNoContent)
}
Explanation of the Code and REST APIs
-
Package and Imports
- The
main
package is used, and necessary packages are imported. go.mongodb.org/mongo-driver/mongo
is used for MongoDB interactions.github.com/gorilla/mux
is used for routing.
- The
-
User Struct
- Represents the
User
model with BSON tags for MongoDB and JSON tags for marshalling/unmarshalling.
- Represents the
-
Global Client Variable
client
is a global variable to hold the MongoDB client.
-
Main Function
- Initializes the MongoDB client.
- Creates a new router using
mux.NewRouter()
. - Defines the REST endpoints and associates them with handler functions.
- Starts the HTTP server on port 8000.
-
getUsers Function
- Retrieves all users from the
users
collection. - Encodes the result as JSON and writes it to the response.
- Retrieves all users from the
-
getUser Function
- Retrieves a single user by ID.
- Returns a 404 error if the user is not found.
-
createUser Function
- Decodes the JSON request body to a
User
struct. - Inserts the new user into the
users
collection. - Returns the created user as JSON.
- Decodes the JSON request body to a
-
updateUser Function
- Decodes the JSON request body to a
User
struct. - Updates the user with the specified ID in the
users
collection. - Returns the updated user as JSON.
- Decodes the JSON request body to a
-
deleteUser Function
- Deletes the user with the specified ID from the
users
collection. - Returns a 204 No Content status on successful deletion.
- Deletes the user with the specified ID from the
Testing with Postman
-
Get All Users
- Method:
GET
- URL:
http://localhost:8000/users
- Response: JSON array of users.
- Method:
-
Get a Single User
- Method:
GET
- URL:
http://localhost:8000/user/{id}
- Response: JSON object of the user.
- Method:
-
Create a New User
- Method:
POST
- URL:
http://localhost:8000/user
- Body:
{ "name": "John Doe", "email": "john@example.com" }
- Response: JSON object of the created user.
- Method:
-
Update an Existing User
- Method:
PUT
- URL:
http://localhost:8000/user/{id}
- Body:
{ "name": "Jane Doe", "email": "jane@example.com" }
- Response: JSON object of the updated user.
- Method:
-
Delete a User
- Method:
DELETE
- URL:
http://localhost:8000/user/{id}
- Response: 204 No Content status.
- Method:
Comments
Post a Comment