Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      Top 15 Enterprise Use Cases That Justify Hiring Node.js Developers in 2025

      July 31, 2025

      The Core Model: Start FROM The Answer, Not WITH The Solution

      July 31, 2025

      AI-Generated Code Poses Major Security Risks in Nearly Half of All Development Tasks, Veracode Research Reveals   

      July 31, 2025

      Understanding the code modernization conundrum

      July 31, 2025

      Not just YouTube: Google is using AI to guess your age based on your activity – everywhere

      July 31, 2025

      Malicious extensions can use ChatGPT to steal your personal data – here’s how

      July 31, 2025

      What Zuckerberg’s ‘personal superintelligence’ sales pitch leaves out

      July 31, 2025

      This handy NordVPN tool flags scam calls on Android – even before you answer

      July 31, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      Route Optimization through Laravel’s Shallow Resource Architecture

      July 31, 2025
      Recent

      Route Optimization through Laravel’s Shallow Resource Architecture

      July 31, 2025

      This Week in Laravel: Laracon News, Free Laravel Idea, and Claude Code Course

      July 31, 2025

      Everything We Know About Pest 4

      July 31, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      FOSS Weekly #25.31: Kernel 6.16, OpenMandriva Review, Conky Customization, System Monitoring and More

      July 31, 2025
      Recent

      FOSS Weekly #25.31: Kernel 6.16, OpenMandriva Review, Conky Customization, System Monitoring and More

      July 31, 2025

      Windows 11’s MSN Widgets board now opens in default browser, such as Chrome (EU only)

      July 31, 2025

      Microsoft’s new “move to Windows 11” campaign implies buying OneDrive paid plan

      July 31, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»Development»How to Use MongoDB with Go

    How to Use MongoDB with Go

    July 31, 2025

    Working with databases is a fundamental part of backend development, particularly when you’re building applications that require persisting, querying, and updating data.

    In Go, the official MongoDB driver provides a robust way to connect to and interact with MongoDB, a flexible NoSQL database that stores data in JSON-like documents.

    In this tutorial, you won’t just learn how to connect Go to MongoDB. You’ll take it a step further by building a simple blog application. Along the way, you’ll learn how to perform essential CRUD (Create, Read, Update, Delete) operations and display your results using the Gin web framework.

    Table of Contents

    • Prerequisites

    • Create a New Go Project

    • Basic MongoDB Operations

      • Insert data into the collection

      • Find documents in MongoDB

      • Update documents in MongoDB

      • Delete documents in MongoDB

    • How to Build a Blog App with go-mongodb-driver and Gin

      • Initialize the Gin application

      • Create the HTML templates

      • Create the handlers

      • Run the application

    • That’s How to Use MongoDB with Go

    Prerequisites

    Before you proceed, ensure that you have the following:

    • Basic knowledge of Go and its concepts

    • Go (version 1.24 or higher) installed

    • MongoDB Installed (running locally on port 27017)

    • Basic knowledge of NoSQL

    Create a New Go Project

    First, create a new Go project, change into the new project directory, and initialize a new Go module by running the following commands:

    mkdir go-mongodb-integration
    cd go-mongodb-integrationgo 
    mod init go-mongodb
    

    Next, install the MongoDB Go driver by running the following command:

    go get go.mongodb.org/mongo-driver/mongo
    go get go.mongodb.org/mongo-driver/bson
    

    The standard Go library includes the database/sql package for working with SQL databases, but it doesn’t support MongoDB out of the box. To work with MongoDB in Go, you’ll use the official MongoDB driver, which provides everything you need to connect to and interact with a MongoDB database.

    With the basic setup complete, let’s now examine basic operations in MongoDB.

    Basic MongoDB Operations

    In MongoDB, databases and collections are created automatically upon the first data insertion, adopting a “lazy creation” approach. Specifically, a database is created when you insert your first document, and a collection is likewise created when data is first inserted into it.

    It’s important to note that functions like client.Database() and db.Collection() only generate references to these structures – they don’t create the actual database or collection until data is inserted.

    Insert data into the collection

    Let’s walk through how to insert a document into a collection in MongoDB.

    First, open your project in a code editor, create a main.go file, and add the following code:

    package main
    
    import (
        "context"
        "log"
        "time"
    
        "go.mongodb.org/mongo-driver/bson/primitive"
        "go.mongodb.org/mongo-driver/mongo"
        "go.mongodb.org/mongo-driver/mongo/options"
    )
    
    type User struct {
        ID   primitive.ObjectID `bson:"_id,omitempty"`
        Name string             `bson:"name"`
        Age  int                `bson:"age"`
    }
    
    func main() {
        clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
    
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
    
        client, err := mongo.Connect(ctx, clientOptions)
        if err != nil {
            log.Fatal(err)
        }
        defer client.Disconnect(ctx)
    
        err = client.Ping(ctx, nil)
        if err != nil {
            log.Fatal(err)
        }
    
        db := client.Database("test_db")
        usersCollection := db.Collection("users")
    
        newUser := User{
            Name: "John Doe",
            Age:  30,
        }
    
        result, err := usersCollection.InsertOne(ctx, newUser)
        if err != nil {
            log.Fatal(err)
        }
    
        log.Printf("Inserted user with ID: %vn", result.InsertedID)
    }
    

    In the code above, you define a User struct that represents your document structure, then insert a new user document into the collection using the InsertOne method. When you run this insert operation, MongoDB automatically creates both the test_db database and the users collection if they don’t already exist.

    Execute the code by running:

    go run main.go
    

    You should see the response below, indicating that a user was inserted successfully.

    A command line interface showing the command `go run main.go` with an output that says, "Inserted user with ID: ObjectID('6862f3112341b0492801633b')" on June 30, 2025.

    Find documents in MongoDB

    Now that you’ve inserted some data, it’s time to query the database and retrieve documents.

    Update your main.go file with the following code:

    package main
    
    import (
        "context"
        "fmt"
        "log"
        "time"
    
        "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"
    )
    
    type User struct {
        ID   primitive.ObjectID `bson:"_id,omitempty"`
        Name string             `bson:"name"`
        Age  int                `bson:"age"`
    }
    
    func main() {
        clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
    
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
    
        client, err := mongo.Connect(ctx, clientOptions)
        if err != nil {
            log.Fatal(err)
        }
        defer client.Disconnect(ctx)
    
        db := client.Database("test_db")
        usersCollection := db.Collection("users")
    
        cursor, err := usersCollection.Find(ctx, bson.M{})
        if err != nil {
            log.Fatal(err)
        }
        defer cursor.Close(ctx)
    
        var users []User
        if err = cursor.All(ctx, &users); err != nil {
            log.Fatal(err)
        }
    
        for _, user := range users {
            fmt.Printf("User: %s, Age: %d, ID: %sn", user.Name, user.Age, user.ID.Hex())
        }
    }
    

    In the code above, you use the Find method with an empty filter (`bson.M{}`) to retrieve all documents from the users collection. Then, you use cursor.All to decode all the results into a slice of User structs.

    Each document is printed to the terminal, showing the name, age, and ID of every user in the collection.

    To run the code, use:

    go run main.go
    

    You should see the response below in your terminal.

    Screenshot of a terminal showing a Go command execution and output with user information including name, age, and ID.

    Update documents in MongoDB

    To update a document in your collection, modify your main.go file as shown below:

    package main
    
    import (
        "context"
        "log"
        "time"
    
        "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"
    )
    
    type User struct {
        ID   primitive.ObjectID `bson:"_id,omitempty"`
        Name string             `bson:"name"`
        Age  int                `bson:"age"`
    }
    
    func main() {
        clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
    
        client, err := mongo.Connect(ctx, clientOptions)
        if err != nil {
            log.Fatal(err)
        }
        defer client.Disconnect(ctx)
    
        db := client.Database("test_db")
        usersCollection := db.Collection("users")
    
        var userToUpdate User
        err = usersCollection.FindOne(ctx, bson.M{"name": "John Doe"}).Decode(&userToUpdate)
        if err != nil {
            log.Println("No user found to update")
        } else {
            update := bson.M{
                "$set": bson.M{
                    "name": "Jane Doe",
                    "age":  25,
                },
            }
            result, err := usersCollection.UpdateOne(
                ctx,
                bson.M{"_id": userToUpdate.ID},
                update,
            )
            if err != nil {
                log.Fatal(err)
            }
            log.Printf("Updated %v document(s)n", result.ModifiedCount)
        }
    }
    

    In the code above, you first search for a user named “John Doe” using the FindOne method. If a match is found, you use the UpdateOne method to update their name and age. The $set operator ensures that only the specified fields are updated, leaving the rest of the document unchanged.

    Execute the code by running:

    go run main.go
    

    You should see output in your terminal indicating how many documents were updated.

    Command line interface showing "go run main.go" and the output "2025/06/30 21:34:36 Updated 1 document(s)".

    Delete documents in MongoDB

    To remove documents from a collection, you can use the DeleteOne method. Update your main.go file with the following code:

    package main
    
    import (
        "context"
        "log"
        "time"
    
        "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"
    )
    
    type User struct {
        ID   primitive.ObjectID `bson:"_id,omitempty"`
        Name string             `bson:"name"`
        Age  int                `bson:"age"`
    }
    
    func main() {
        clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
    
        client, err := mongo.Connect(ctx, clientOptions)
        if err != nil {
            log.Fatal(err)
        }
        defer client.Disconnect(ctx)
    
        db := client.Database("test_db")
        usersCollection := db.Collection("users")
    
        result, err := usersCollection.DeleteOne(ctx, bson.M{"name": "Jane Doe"})
        if err != nil {
            log.Fatal(err)
        }
        log.Printf("Deleted %v document(s)n", result.DeletedCount)
    }
    

    In the code above, you use the DeleteOne method to remove the first document that matches the filter { "name": "Jane Doe" }.

    You should see the result below in your terminal.

    A command line terminal showing the execution of "go run main.go" and outputting "2025/06/30 21:36:05 Deleted 1 document(s)".

    How to Build a Blog App with go-mongodb-driver and Gin

    Now that you understand how to perform basic CRUD operations with MongoDB in Go, you’re ready to build a more complete application.

    Start by creating a new directory for your project and initializing it as a Go module. Navigate to your chosen directory and run:

    mkdir go-blog
    cd go-blog
    go mod init blog
    

    Next, install the required dependencies:

    go get github.com/gin-gonic/gin
    go get go.mongodb.org/mongo-driver/mongo
    go get go.mongodb.org/mongo-driver/bson
    

    Your project will have the following structure:

    go-blog/  
    ├── main.go  
    ├── handlers/  
    │   └── main.go  
    └── templates/  
        ├── index.html  
        ├── post.html  
        ├── create.html  
        └── edit.html
    

    Initialize the Gin application

    To initialize a new Gin application, create a new main.go file and add the below code snippet to it:

    package main
    
    import (
        "context"
        "log"
        "time"
    
        "blog/handlers"
    
        "github.com/gin-gonic/gin"
        "go.mongodb.org/mongo-driver/mongo"
        "go.mongodb.org/mongo-driver/mongo/options"
    )
    
    func main() {
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
    
        clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
        client, err := mongo.Connect(ctx, clientOptions)
        if err != nil {
            log.Fatal(err)
        }
        defer client.Disconnect(ctx)
    
        err = client.Ping(ctx, nil)
        if err != nil {
            log.Fatal(err)
        }
        log.Println("Connected to MongoDB!")
    
        db := client.Database("blog_db")
        h := handlers.NewHandler(db)
    
        router := gin.Default()
        router.LoadHTMLGlob("templates/*")
    
        router.GET("/", h.HomePage)
        router.GET("/post/:id", h.ViewPost)
        router.GET("/create", h.CreatePost)
        router.GET("/edit/:id", h.EditPost)
        router.POST("/save", h.SavePost)
        router.GET("/delete/:id", h.DeletePost)
    
        log.Println("Server starting on :8080...")
        router.Run(":8080")
    }
    

    The code above sets up the MongoDB connection, initializes the Gin router, and registers your routes.

    Create the HTML templates

    Now, create the HTML templates for displaying the blog UI.

    First, create a templates directory and add the following files:

    index.html:

    <!DOCTYPE html>  
    <html lang="en">  
    <head>  
        <meta charset="UTF-8">  
        <meta name="viewport" content="width=device-width, initial-scale=1.0">  
        <title>Go Blog with MongoDB</title>  
        <script src="https://cdn.tailwindcss.com"></script>  
    </head>  
    <body class="bg-gray-100 min-h-screen">  
        <div class="container mx-auto px-4 py-8">  
            <header class="mb-8">  
                <h1 class="text-3xl font-bold text-center text-blue-600">Go Blog with MongoDB</h1>  
                <div class="flex justify-center mt-4">  
                    <a href="/create" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">Create New Post</a>  
                </div>  
            </header>
    
            <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">  
                {{range .}}  
                <div class="bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition-shadow duration-300">  
                    <div class="p-6">  
                        <h2 class="text-xl font-semibold mb-2 text-gray-800">{{.Title}}</h2>  
                        <p class="text-gray-600 mb-4 line-clamp-3">  
                            {{if gt (len .Content) 150}}  
                                {{slice .Content 0 150}}...  
                            {{else}}  
                                {{.Content}}  
                            {{end}}  
                        </p>  
                        <div class="flex justify-between items-center text-sm text-gray-500">  
                            <span>{{.CreatedAt.Format "Jan 02, 2006"}}</span>  
                            <a href="/post/{{.ID.Hex}}" class="text-blue-500 hover:text-blue-700">Read More</a>  
                        </div>  
                    </div>  
                    <div class="flex border-t border-gray-200">  
                        <a href="/edit/{{.ID.Hex}}" class="w-1/2 py-2 text-center text-sm text-gray-600 hover:bg-gray-100 border-r border-gray-200">Edit</a>  
                        <a href="/delete/{{.ID.Hex}}" class="w-1/2 py-2 text-center text-sm text-red-600 hover:bg-gray-100" onclick="return confirm('Are you sure you want to delete this post?')">Delete</a>  
                    </div>  
                </div>  
                {{else}}  
                <div class="col-span-3 text-center py-12">  
                    <p class="text-gray-600 text-lg">No posts yet. <a href="/create" class="text-blue-500 hover:underline">Create one</a>!</p>  
                </div>  
                {{end}}  
            </div>  
        </div>  
    </body>  
    </html>
    

    This template lists all blog posts and includes buttons to create, edit, or delete posts.

    post.html:

    <!DOCTYPE html>  
    <html lang="en">  
    <head>  
        <meta charset="UTF-8">  
        <meta name="viewport" content="width=device-width, initial-scale=1.0">  
        <title>{{.Title}} | Go Blog with MongoDB</title>  
        <script src="https://cdn.tailwindcss.com"></script>  
    </head>  
    <body class="bg-gray-100 min-h-screen">  
        <div class="container mx-auto px-4 py-8">  
            <header class="mb-8">  
                <h1 class="text-3xl font-bold text-center text-blue-600">Go Blog with MongoDB</h1>  
                <div class="flex justify-center mt-4">  
                    <a href="/" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">Back to Home</a>  
                </div>  
            </header>
    
            <div class="max-w-3xl mx-auto bg-white rounded-lg shadow-md overflow-hidden">  
                <div class="p-6">  
                    <h2 class="text-2xl font-bold mb-4 text-gray-800">{{.Title}}</h2>  
    
                    <div class="flex items-center text-sm text-gray-500 mb-6">  
                        <span>Posted: {{.CreatedAt.Format "Jan 02, 2006"}}</span>  
                        {{if ne .CreatedAt .UpdatedAt}}  
                        <span class="mx-2">•</span>  
                        <span>Updated: {{.UpdatedAt.Format "Jan 02, 2006"}}</span>  
                        {{end}}  
                    </div>  
    
                    <div class="prose max-w-none">  
                        <p class="text-gray-700 whitespace-pre-line">{{.Content}}</p>  
                    </div>  
                </div>  
    
                <div class="flex border-t border-gray-200">  
                    <a href="/edit/{{.ID.Hex}}" class="w-1/2 py-3 text-center text-blue-600 hover:bg-gray-100 border-r border-gray-200">Edit Post</a>  
                    <a href="/delete/{{.ID.Hex}}" class="w-1/2 py-3 text-center text-red-600 hover:bg-gray-100" onclick="return confirm('Are you sure you want to delete this post?')">Delete Post</a>  
                </div>  
            </div>  
        </div>  
    </body>  
    </html>
    

    This template displays a single post.

    create.html:

    <!DOCTYPE html>  
    <html lang="en">  
    <head>  
        <meta charset="UTF-8">  
        <meta name="viewport" content="width=device-width, initial-scale=1.0">  
        <title>Create New Post | Go Blog with MongoDB</title>  
        <script src="https://cdn.tailwindcss.com"></script>  
    </head>  
    <body class="bg-gray-100 min-h-screen">  
        <div class="container mx-auto px-4 py-8">  
            <header class="mb-8">  
                <h1 class="text-3xl font-bold text-center text-blue-600">Go Blog with MongoDB</h1>  
                <div class="flex justify-center mt-4">  
                    <a href="/" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">Back to Home</a>  
                </div>  
            </header>
    
            <div class="max-w-2xl mx-auto bg-white rounded-lg shadow-md overflow-hidden">  
                <div class="p-6">  
                    <h2 class="text-2xl font-bold mb-6 text-gray-800">Create New Post</h2>  
    
                    <form action="/save" method="POST">  
                        <div class="mb-4">  
                            <label for="title" class="block text-gray-700 font-medium mb-2">Title</label>  
                            <input type="text" id="title" name="title" required  
                                class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">  
                        </div>  
    
                        <div class="mb-6">  
                            <label for="content" class="block text-gray-700 font-medium mb-2">Content</label>  
                            <textarea id="content" name="content" rows="10" required  
                                class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"></textarea>  
                        </div>  
    
                        <div class="flex justify-end">  
                            <button type="submit" class="bg-blue-500 hover:bg-blue-600 text-white px-6 py-2 rounded-md">  
                                Save Post  
                            </button>  
                        </div>  
                    </form>  
                </div>  
            </div>  
        </div>  
    </body>  
    </html>
    

    This template allows you to create a new post.

    edit.html:

    <!DOCTYPE html>  
    <html lang="en">  
    <head>  
        <meta charset="UTF-8">  
        <meta name="viewport" content="width=device-width, initial-scale=1.0">  
        <title>Edit Post | Go Blog with MongoDB</title>  
        <script src="https://cdn.tailwindcss.com"></script>  
    </head>  
    <body class="bg-gray-100 min-h-screen">  
        <div class="container mx-auto px-4 py-8">  
            <header class="mb-8">  
                <h1 class="text-3xl font-bold text-center text-blue-600">Go Blog with MongoDB</h1>  
                <div class="flex justify-center mt-4">  
                    <a href="/" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">Back to Home</a>  
                </div>  
            </header>
    
            <div class="max-w-2xl mx-auto bg-white rounded-lg shadow-md overflow-hidden">  
                <div class="p-6">  
                    <h2 class="text-2xl font-bold mb-6 text-gray-800">Edit Post</h2>  
    
                    <form action="/save" method="POST">  
                        <input type="hidden" name="id" value="{{.ID.Hex}}">  
    
                        <div class="mb-4">  
                            <label for="title" class="block text-gray-700 font-medium mb-2">Title</label>  
                            <input type="text" id="title" name="title" value="{{.Title}}" required  
                                class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">  
                        </div>  
    
                        <div class="mb-6">  
                            <label for="content" class="block text-gray-700 font-medium mb-2">Content</label>  
                            <textarea id="content" name="content" rows="10" required  
                                class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">{{.Content}}</textarea>  
                        </div>  
    
                        <div class="flex justify-between">  
                            <a href="/post/{{.ID.Hex}}" class="text-gray-600 hover:text-gray-800">Cancel</a>  
                            <button type="submit" class="bg-blue-500 hover:bg-blue-600 text-white px-6 py-2 rounded-md">  
                                Update Post  
                            </button>  
                        </div>  
                    </form>  
                </div>  
            </div>  
        </div>  
    </body>  
    </html>
    

    This template is used to edit a post.

    Create the handlers

    Next, set up the handlers to connect with MongoDB and render the templates. Create a new folder called handlers in your project’s root directory, then add a main.go file inside it and insert the following code snippet:

    package handlers
    
    import (
        "context"
        "log"
        "net/http"
        "time"
    
        "github.com/gin-gonic/gin"
        "go.mongodb.org/mongo-driver/bson"
        "go.mongodb.org/mongo-driver/bson/primitive"
        "go.mongodb.org/mongo-driver/mongo"
    )
    
    type Post struct {
        ID        primitive.ObjectID `bson:"_id,omitempty" json:"id"`
        Title     string             `bson:"title" json:"title"`
        Content   string             `bson:"content" json:"content"`
        CreatedAt time.Time          `bson:"created_at" json:"created_at"`
        UpdatedAt time.Time          `bson:"updated_at" json:"updated_at"`
    }
    
    type Handler struct {
        db         *mongo.Database
        collection *mongo.Collection
    }
    
    func NewHandler(db *mongo.Database) *Handler {
        return &Handler{
            db:         db,
            collection: db.Collection("posts"),
        }
    }
    
    func (h *Handler) HomePage(c *gin.Context) {
        ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
        defer cancel()
    
        cursor, err := h.collection.Find(ctx, bson.M{})
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
        defer cursor.Close(ctx)
    
        var posts []Post
        if err = cursor.All(ctx, &posts); err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
    
        c.HTML(http.StatusOK, "index.html", posts)
    }
    
    func (h *Handler) ViewPost(c *gin.Context) {
        id := c.Param("id")
        objID, err := primitive.ObjectIDFromHex(id)
        if err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid post ID"})
            return
        }
    
        ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
        defer cancel()
    
        var post Post
        err = h.collection.FindOne(ctx, bson.M{"_id": objID}).Decode(&post)
        if err != nil {
            c.JSON(http.StatusNotFound, gin.H{"error": "Post not found"})
            return
        }
    
        c.HTML(http.StatusOK, "post.html", post)
    }
    
    func (h *Handler) CreatePost(c *gin.Context) {
        c.HTML(http.StatusOK, "create.html", nil)
    }
    
    func (h *Handler) EditPost(c *gin.Context) {
        id := c.Param("id")
        objID, err := primitive.ObjectIDFromHex(id)
        if err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid post ID"})
            return
        }
    
        ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
        defer cancel()
    
        var post Post
        err = h.collection.FindOne(ctx, bson.M{"_id": objID}).Decode(&post)
        if err != nil {
            c.JSON(http.StatusNotFound, gin.H{"error": "Post not found"})
            return
        }
    
        c.HTML(http.StatusOK, "edit.html", post)
    }
    
    func (h *Handler) SavePost(c *gin.Context) {
        ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
        defer cancel()
    
        id := c.PostForm("id")
        title := c.PostForm("title")
        content := c.PostForm("content")
    
        now := time.Now()
    
        if id == "" {
            post := Post{
                Title:     title,
                Content:   content,
                CreatedAt: now,
                UpdatedAt: now,
            }
    
            result, err := h.collection.InsertOne(ctx, post)
            if err != nil {
                c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
                return
            }
    
            log.Printf("Created post with ID: %vn", result.InsertedID)
        } else {
            objID, err := primitive.ObjectIDFromHex(id)
            if err != nil {
                c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid post ID"})
                return
            }
    
            update := bson.M{
                "$set": bson.M{
                    "title":      title,
                    "content":    content,
                    "updated_at": now,
                },
            }
    
            result, err := h.collection.UpdateOne(ctx, bson.M{"_id": objID}, update)
            if err != nil {
                c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
                return
            }
    
            log.Printf("Updated post with ID: %s (Modified %d documents)n", id, result.ModifiedCount)
        }
    
        c.Redirect(http.StatusSeeOther, "/")
    }
    
    func (h *Handler) DeletePost(c *gin.Context) {
        id := c.Param("id")
        objID, err := primitive.ObjectIDFromHex(id)
        if err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid post ID"})
            return
        }
    
        ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
        defer cancel()
    
        result, err := h.collection.DeleteOne(ctx, bson.M{"_id": objID})
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
    
        log.Printf("Deleted %d document(s) with ID: %sn", result.DeletedCount, id)
        c.Redirect(http.StatusSeeOther, "/")
    }
    

    The code above contains all the logic for managing blog posts. Here’s what each component does:

    • Post struct: Defines the structure of a blog post document with fields for ID, title, content, and timestamps. The bson tags specify how fields are stored in MongoDB, while json tags handle JSON serialization.

    • Handler struct: Contains a reference to the MongoDB database and the posts collection, providing a centralized way to access the database throughout your handlers.

    • NewHandler function: Creates and initializes a new handler instance with the database connection and sets up the posts collection reference.

    • HomePage: Retrieves all blog posts from the database using Find() with an empty filter and renders them using the index.html template.

    • ViewPost: Fetches a single post by its ObjectID using FindOne() and displays it with the post.html template.

    • CreatePost & EditPost: Render the respective forms for creating new posts or editing existing ones.

    • SavePost: Handles both creating new posts and updating existing ones. It checks if an ID is provided. If not, it creates a new post using InsertOne(). Otherwise, it updates the existing post using UpdateOne() with MongoDB’s $set operator.

    • DeletePost: Removes a post from the database using DeleteOne() and redirects back to the homepage.

    Run the application

    With everything set up, you can now launch your blog. Open your terminal and run:

    go mod tidy && go run main.go
    

    Then, visit http://localhost:8080 in your browser to see your blog in action.

    Blog management interface with a header "Go Blog with MongoDB" and a "Create New Post" button. Two blog post entries are shown with options to edit or delete.

    That’s How to Use MongoDB with Go

    In this tutorial, you built a simple blog application using Go and MongoDB. You learned how to connect to a MongoDB database using the official Go driver, perform CRUD operations, and render your results with the Gin web framework.

    MongoDB’s flexible, document-based structure makes it a great fit for applications where data models need to evolve over time. It allows you to iterate quickly and adapt as your app grows.

    As you expand this project, consider adding features such as user authentication, tagging or categorization, comments, pagination, or search functionality to enhance the user experience.

    Cheers to building more with Go and MongoDB!

    Source: freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleWhat is Unicode —The Secret Language Behind Every Text You See
    Next Article How to Upload Large Objects to S3 with AWS CLI Multipart Upload

    Related Posts

    Development

    Route Optimization through Laravel’s Shallow Resource Architecture

    July 31, 2025
    Development

    This Week in Laravel: Laracon News, Free Laravel Idea, and Claude Code Course

    July 31, 2025
    Leave A Reply Cancel Reply

    For security, use of Google's reCAPTCHA service is required which is subject to the Google Privacy Policy and Terms of Use.

    Continue Reading

    Sensitive Gangsta Merch

    Web Development

    CVE-2025-44998 – TinyFileManager Stored XSS

    Common Vulnerabilities and Exposures (CVEs)

    Zenless Zone Zero’s Xbox release date has finally been announced to the world

    News & Updates

    GPD MicroPC 2: Souped-Up Successor to Original Pocket PC

    Linux

    Highlights

    CVE-2025-41404 – Iroha Board Information Disclosure

    June 26, 2025

    CVE ID : CVE-2025-41404

    Published : June 26, 2025, 6:15 a.m. | 4 hours, 48 minutes ago

    Description : Direct request (‘Forced Browsing’) issue exists in iroha Board versions v0.10.12 and earlier. If this vulnerability is exploited, non-public contents may be viewed by an attacker who can log in to the affected product.

    Severity: 4.3 | MEDIUM

    Visit the link for more details, such as CVSS details, affected products, timeline, and more…

    Europol shuts down Ramnit botnet used to steal bank details

    April 9, 2025

    I’ve loved using this wireless gaming headset since the day I reviewed it — I can’t believe it’s almost $100 off for Amazon Prime Day

    July 10, 2025

    shotgun is a minimal screenshot utility for X11

    April 3, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.