<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Oluwadamilola Oshungboye - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Oluwadamilola Oshungboye - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 22:23:58 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/ThatCoolGuy/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Use MongoDB with Go ]]>
                </title>
                <description>
                    <![CDATA[ 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 inter... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-mongodb-with-go/</link>
                <guid isPermaLink="false">688b03e7d853646bf4658392</guid>
                
                    <category>
                        <![CDATA[ Go Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MongoDB ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Tutorial ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwadamilola Oshungboye ]]>
                </dc:creator>
                <pubDate>Thu, 31 Jul 2025 05:49:27 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1753940956019/6551a007-b463-486f-8746-15c13a7a99a0.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Working with databases is a fundamental part of backend development, particularly when you’re building applications that require persisting, querying, and updating data.</p>
<p>In Go, the <a target="_blank" href="https://github.com/mongodb/mongo-go-driver">official MongoDB driver</a> provides a robust way to connect to and interact with MongoDB, a flexible NoSQL database that stores data in JSON-like documents.</p>
<p>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.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-create-a-new-go-project">Create a New Go Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-basic-mongodb-operations">Basic MongoDB Operations</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-insert-data-into-the-collection">Insert data into the collection</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-find-documents-in-mongodb">Find documents in MongoDB</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-update-documents-in-mongodb">Update documents in MongoDB</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-delete-documents-in-mongodb">Delete documents in MongoDB</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-a-blog-app-with-go-mongodb-driver-and-gin">How to Build a Blog App with go-mongodb-driver and Gin</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-initialize-the-gin-application">Initialize the Gin application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-create-the-html-templates">Create the HTML templates</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-create-the-handlers">Create the handlers</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-run-the-application">Run the application</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-thats-how-to-use-mongodb-with-go">That's How to Use MongoDB with Go</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you proceed, ensure that you have the following:</p>
<ul>
<li><p>Basic knowledge of <a target="_blank" href="https://go.dev/">Go</a> and its concepts</p>
</li>
<li><p>Go (version 1.24 or higher) installed</p>
</li>
<li><p><a target="_blank" href="https://www.mongodb.com/docs/manual/installation/">MongoDB</a> Installed (running locally on port 27017)</p>
</li>
<li><p>Basic knowledge of NoSQL</p>
</li>
</ul>
<h2 id="heading-create-a-new-go-project">Create a New Go Project</h2>
<p>First, create a new Go project, change into the new project directory, and initialize a new Go module by running the following commands:</p>
<pre><code class="lang-bash">mkdir go-mongodb-integration
<span class="hljs-built_in">cd</span> go-mongodb-integrationgo 
mod init go-mongodb
</code></pre>
<p>Next, install the MongoDB Go driver by running the following command:</p>
<pre><code class="lang-bash">go get go.mongodb.org/mongo-driver/mongo
go get go.mongodb.org/mongo-driver/bson
</code></pre>
<p>The standard Go library includes the <code>database/sql</code> 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.</p>
<p>With the basic setup complete, let’s now examine basic operations in MongoDB.</p>
<h2 id="heading-basic-mongodb-operations">Basic MongoDB Operations</h2>
<p>In MongoDB, databases and <a target="_blank" href="https://www.mongodb.com/docs/manual/reference/glossary/#std-term-collection">collections</a> 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.</p>
<p>It's important to note that functions like <code>client.Database()</code> and <code>db.Collection()</code> only generate references to these structures – they don’t create the actual database or collection until data is inserted.</p>
<h3 id="heading-insert-data-into-the-collection">Insert data into the collection</h3>
<p>Let’s walk through how to insert a document into a collection in MongoDB.</p>
<p>First, open your project in a code editor, create a <code>main.go</code> file, and add the following code:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"context"</span>
    <span class="hljs-string">"log"</span>
    <span class="hljs-string">"time"</span>

    <span class="hljs-string">"go.mongodb.org/mongo-driver/bson/primitive"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/mongo"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/mongo/options"</span>
)

<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
    ID   primitive.ObjectID <span class="hljs-string">`bson:"_id,omitempty"`</span>
    Name <span class="hljs-keyword">string</span>             <span class="hljs-string">`bson:"name"`</span>
    Age  <span class="hljs-keyword">int</span>                <span class="hljs-string">`bson:"age"`</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    clientOptions := options.Client().ApplyURI(<span class="hljs-string">"mongodb://localhost:27017"</span>)

    ctx, cancel := context.WithTimeout(context.Background(), <span class="hljs-number">10</span>*time.Second)
    <span class="hljs-keyword">defer</span> cancel()

    client, err := mongo.Connect(ctx, clientOptions)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        log.Fatal(err)
    }
    <span class="hljs-keyword">defer</span> client.Disconnect(ctx)

    err = client.Ping(ctx, <span class="hljs-literal">nil</span>)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        log.Fatal(err)
    }

    db := client.Database(<span class="hljs-string">"test_db"</span>)
    usersCollection := db.Collection(<span class="hljs-string">"users"</span>)

    newUser := User{
        Name: <span class="hljs-string">"John Doe"</span>,
        Age:  <span class="hljs-number">30</span>,
    }

    result, err := usersCollection.InsertOne(ctx, newUser)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        log.Fatal(err)
    }

    log.Printf(<span class="hljs-string">"Inserted user with ID: %v\n"</span>, result.InsertedID)
}
</code></pre>
<p>In the code above, you define a <code>User</code> <a target="_blank" href="https://www.w3schools.com/go/go_struct.php">struct</a> that represents your document structure, then insert a new user document into the collection using the <code>InsertOne</code> method. When you run this insert operation, MongoDB automatically creates both the <code>test_db</code> database and the <code>users</code> collection if they don’t already exist.</p>
<p>Execute the code by running:</p>
<pre><code class="lang-bash">go run main.go
</code></pre>
<p>You should see the response below, indicating that a user was inserted successfully.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753561045916/79c1f4f1-ebe1-41e8-b6dd-01a5e2c9d247.png" alt="A command line interface showing the command `go run main.go` with an output that says, &quot;Inserted user with ID: ObjectID('6862f3112341b0492801633b')&quot; on June 30, 2025." class="image--center mx-auto" width="1068" height="130" loading="lazy"></p>
<h3 id="heading-find-documents-in-mongodb">Find documents in MongoDB</h3>
<p>Now that you've inserted some data, it's time to query the database and retrieve documents.</p>
<p>Update your <code>main.go</code> file with the following code:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"context"</span>
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"log"</span>
    <span class="hljs-string">"time"</span>

    <span class="hljs-string">"go.mongodb.org/mongo-driver/bson"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/bson/primitive"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/mongo"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/mongo/options"</span>
)

<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
    ID   primitive.ObjectID <span class="hljs-string">`bson:"_id,omitempty"`</span>
    Name <span class="hljs-keyword">string</span>             <span class="hljs-string">`bson:"name"`</span>
    Age  <span class="hljs-keyword">int</span>                <span class="hljs-string">`bson:"age"`</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    clientOptions := options.Client().ApplyURI(<span class="hljs-string">"mongodb://localhost:27017"</span>)

    ctx, cancel := context.WithTimeout(context.Background(), <span class="hljs-number">10</span>*time.Second)
    <span class="hljs-keyword">defer</span> cancel()

    client, err := mongo.Connect(ctx, clientOptions)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        log.Fatal(err)
    }
    <span class="hljs-keyword">defer</span> client.Disconnect(ctx)

    db := client.Database(<span class="hljs-string">"test_db"</span>)
    usersCollection := db.Collection(<span class="hljs-string">"users"</span>)

    cursor, err := usersCollection.Find(ctx, bson.M{})
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        log.Fatal(err)
    }
    <span class="hljs-keyword">defer</span> cursor.Close(ctx)

    <span class="hljs-keyword">var</span> users []User
    <span class="hljs-keyword">if</span> err = cursor.All(ctx, &amp;users); err != <span class="hljs-literal">nil</span> {
        log.Fatal(err)
    }

    <span class="hljs-keyword">for</span> _, user := <span class="hljs-keyword">range</span> users {
        fmt.Printf(<span class="hljs-string">"User: %s, Age: %d, ID: %s\n"</span>, user.Name, user.Age, user.ID.Hex())
    }
}
</code></pre>
<p>In the code above, you use the <code>Find</code> method with an empty filter (`bson.M{}`) to retrieve all documents from the <code>users</code> collection. Then, you use <code>cursor.All</code> to decode all the results into a slice of <code>User</code> structs.</p>
<p>Each document is printed to the terminal, showing the name, age, and ID of every user in the collection.</p>
<p>To run the code, use:</p>
<pre><code class="lang-bash">go run main.go
</code></pre>
<p>You should see the response below in your terminal.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753561158932/adc32e01-742e-4c5c-acf8-a83e1197a27c.png" alt="Screenshot of a terminal showing a Go command execution and output with user information including name, age, and ID." width="512" height="83" loading="lazy"></p>
<h3 id="heading-update-documents-in-mongodb">Update documents in MongoDB</h3>
<p>To update a document in your collection, modify your <code>main.go</code> file as shown below:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"context"</span>
    <span class="hljs-string">"log"</span>
    <span class="hljs-string">"time"</span>

    <span class="hljs-string">"go.mongodb.org/mongo-driver/bson"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/bson/primitive"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/mongo"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/mongo/options"</span>
)

<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
    ID   primitive.ObjectID <span class="hljs-string">`bson:"_id,omitempty"`</span>
    Name <span class="hljs-keyword">string</span>             <span class="hljs-string">`bson:"name"`</span>
    Age  <span class="hljs-keyword">int</span>                <span class="hljs-string">`bson:"age"`</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    clientOptions := options.Client().ApplyURI(<span class="hljs-string">"mongodb://localhost:27017"</span>)
    ctx, cancel := context.WithTimeout(context.Background(), <span class="hljs-number">10</span>*time.Second)
    <span class="hljs-keyword">defer</span> cancel()

    client, err := mongo.Connect(ctx, clientOptions)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        log.Fatal(err)
    }
    <span class="hljs-keyword">defer</span> client.Disconnect(ctx)

    db := client.Database(<span class="hljs-string">"test_db"</span>)
    usersCollection := db.Collection(<span class="hljs-string">"users"</span>)

    <span class="hljs-keyword">var</span> userToUpdate User
    err = usersCollection.FindOne(ctx, bson.M{<span class="hljs-string">"name"</span>: <span class="hljs-string">"John Doe"</span>}).Decode(&amp;userToUpdate)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        log.Println(<span class="hljs-string">"No user found to update"</span>)
    } <span class="hljs-keyword">else</span> {
        update := bson.M{
            <span class="hljs-string">"$set"</span>: bson.M{
                <span class="hljs-string">"name"</span>: <span class="hljs-string">"Jane Doe"</span>,
                <span class="hljs-string">"age"</span>:  <span class="hljs-number">25</span>,
            },
        }
        result, err := usersCollection.UpdateOne(
            ctx,
            bson.M{<span class="hljs-string">"_id"</span>: userToUpdate.ID},
            update,
        )
        <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
            log.Fatal(err)
        }
        log.Printf(<span class="hljs-string">"Updated %v document(s)\n"</span>, result.ModifiedCount)
    }
}
</code></pre>
<p>In the code above, you first search for a user named "John Doe" using the <code>FindOne</code> method. If a match is found, you use the <code>UpdateOne</code> method to update their name and age. The <code>$set</code> operator ensures that only the specified fields are updated, leaving the rest of the document unchanged.</p>
<p>Execute the code by running:</p>
<pre><code class="lang-bash">go run main.go
</code></pre>
<p>You should see output in your terminal indicating how many documents were updated.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753561280040/73f7a859-5d7a-440a-a58b-b6105b8837ab.png" alt="Command line interface showing &quot;go run main.go&quot; and the output &quot;2025/06/30 21:34:36 Updated 1 document(s)&quot;." width="512" height="89" loading="lazy"></p>
<h3 id="heading-delete-documents-in-mongodb">Delete documents in MongoDB</h3>
<p>To remove documents from a collection, you can use the <code>DeleteOne</code> method. Update your <code>main.go</code> file with the following code:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"context"</span>
    <span class="hljs-string">"log"</span>
    <span class="hljs-string">"time"</span>

    <span class="hljs-string">"go.mongodb.org/mongo-driver/bson"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/bson/primitive"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/mongo"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/mongo/options"</span>
)

<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
    ID   primitive.ObjectID <span class="hljs-string">`bson:"_id,omitempty"`</span>
    Name <span class="hljs-keyword">string</span>             <span class="hljs-string">`bson:"name"`</span>
    Age  <span class="hljs-keyword">int</span>                <span class="hljs-string">`bson:"age"`</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    clientOptions := options.Client().ApplyURI(<span class="hljs-string">"mongodb://localhost:27017"</span>)
    ctx, cancel := context.WithTimeout(context.Background(), <span class="hljs-number">10</span>*time.Second)
    <span class="hljs-keyword">defer</span> cancel()

    client, err := mongo.Connect(ctx, clientOptions)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        log.Fatal(err)
    }
    <span class="hljs-keyword">defer</span> client.Disconnect(ctx)

    db := client.Database(<span class="hljs-string">"test_db"</span>)
    usersCollection := db.Collection(<span class="hljs-string">"users"</span>)

    result, err := usersCollection.DeleteOne(ctx, bson.M{<span class="hljs-string">"name"</span>: <span class="hljs-string">"Jane Doe"</span>})
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        log.Fatal(err)
    }
    log.Printf(<span class="hljs-string">"Deleted %v document(s)\n"</span>, result.DeletedCount)
}
</code></pre>
<p>In the code above, you use the <code>DeleteOne</code> method to remove the first document that matches the filter <code>{ "name": "Jane Doe" }</code>.</p>
<p>You should see the result below in your terminal.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753561355070/ab8797ef-8a15-47e0-8502-9b120fbbd2b8.png" alt="A command line terminal showing the execution of &quot;go run main.go&quot; and outputting &quot;2025/06/30 21:36:05 Deleted 1 document(s)&quot;." width="512" height="84" loading="lazy"></p>
<h2 id="heading-how-to-build-a-blog-app-with-go-mongodb-driver-and-gin">How to Build a Blog App with go-mongodb-driver and Gin</h2>
<p>Now that you understand how to perform basic CRUD operations with MongoDB in Go, you're ready to build a more complete application.</p>
<p>Start by creating a new directory for your project and initializing it as a Go module. Navigate to your chosen directory and run:</p>
<pre><code class="lang-bash">mkdir go-blog
<span class="hljs-built_in">cd</span> go-blog
go mod init blog
</code></pre>
<p>Next, install the required dependencies:</p>
<pre><code class="lang-bash">go get github.com/gin-gonic/gin
go get go.mongodb.org/mongo-driver/mongo
go get go.mongodb.org/mongo-driver/bson
</code></pre>
<p>Your project will have the following structure:</p>
<pre><code class="lang-bash">go-blog/  
├── main.go  
├── handlers/  
│   └── main.go  
└── templates/  
    ├── index.html  
    ├── post.html  
    ├── create.html  
    └── edit.html
</code></pre>
<h3 id="heading-initialize-the-gin-application">Initialize the Gin application</h3>
<p>To initialize a new Gin application, create a new <code>main.go</code> file and add the below code snippet to it:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"context"</span>
    <span class="hljs-string">"log"</span>
    <span class="hljs-string">"time"</span>

    <span class="hljs-string">"blog/handlers"</span>

    <span class="hljs-string">"github.com/gin-gonic/gin"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/mongo"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/mongo/options"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    ctx, cancel := context.WithTimeout(context.Background(), <span class="hljs-number">10</span>*time.Second)
    <span class="hljs-keyword">defer</span> cancel()

    clientOptions := options.Client().ApplyURI(<span class="hljs-string">"mongodb://localhost:27017"</span>)
    client, err := mongo.Connect(ctx, clientOptions)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        log.Fatal(err)
    }
    <span class="hljs-keyword">defer</span> client.Disconnect(ctx)

    err = client.Ping(ctx, <span class="hljs-literal">nil</span>)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        log.Fatal(err)
    }
    log.Println(<span class="hljs-string">"Connected to MongoDB!"</span>)

    db := client.Database(<span class="hljs-string">"blog_db"</span>)
    h := handlers.NewHandler(db)

    router := gin.Default()
    router.LoadHTMLGlob(<span class="hljs-string">"templates/*"</span>)

    router.GET(<span class="hljs-string">"/"</span>, h.HomePage)
    router.GET(<span class="hljs-string">"/post/:id"</span>, h.ViewPost)
    router.GET(<span class="hljs-string">"/create"</span>, h.CreatePost)
    router.GET(<span class="hljs-string">"/edit/:id"</span>, h.EditPost)
    router.POST(<span class="hljs-string">"/save"</span>, h.SavePost)
    router.GET(<span class="hljs-string">"/delete/:id"</span>, h.DeletePost)

    log.Println(<span class="hljs-string">"Server starting on :8080..."</span>)
    router.Run(<span class="hljs-string">":8080"</span>)
}
</code></pre>
<p>The code above sets up the MongoDB connection, initializes the Gin router, and registers your routes.</p>
<h3 id="heading-create-the-html-templates">Create the HTML templates</h3>
<p>Now, create the HTML templates for displaying the blog UI.</p>
<p>First, create a <code>templates</code> directory and add the following files:</p>
<h4 id="heading-indexhtml">index.html:</h4>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>  
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>  
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Go Blog with MongoDB<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.tailwindcss.com"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>  
<span class="hljs-tag">&lt;<span class="hljs-name">body</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-gray-100 min-h-screen"</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container mx-auto px-4 py-8"</span>&gt;</span>  
        <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-8"</span>&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-3xl font-bold text-center text-blue-600"</span>&gt;</span>Go Blog with MongoDB<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex justify-center mt-4"</span>&gt;</span>  
                <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/create"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded"</span>&gt;</span>Create New Post<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>  
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
        <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>

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

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"max-w-3xl mx-auto bg-white rounded-lg shadow-md overflow-hidden"</span>&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"p-6"</span>&gt;</span>  
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-2xl font-bold mb-4 text-gray-800"</span>&gt;</span>{{.Title}}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>  

                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex items-center text-sm text-gray-500 mb-6"</span>&gt;</span>  
                    <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Posted: {{.CreatedAt.Format "Jan 02, 2006"}}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>  
                    {{if ne .CreatedAt .UpdatedAt}}  
                    <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mx-2"</span>&gt;</span>•<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>  
                    <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Updated: {{.UpdatedAt.Format "Jan 02, 2006"}}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>  
                    {{end}}  
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  

                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"prose max-w-none"</span>&gt;</span>  
                    <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-gray-700 whitespace-pre-line"</span>&gt;</span>{{.Content}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>  
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  

            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex border-t border-gray-200"</span>&gt;</span>  
                <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/edit/{{.ID.Hex}}"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"w-1/2 py-3 text-center text-blue-600 hover:bg-gray-100 border-r border-gray-200"</span>&gt;</span>Edit Post<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>  
                <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/delete/{{.ID.Hex}}"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"w-1/2 py-3 text-center text-red-600 hover:bg-gray-100"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"return confirm('Are you sure you want to delete this post?')"</span>&gt;</span>Delete Post<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>  
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>This template displays a single post.</p>
<h4 id="heading-createhtml">create.html:</h4>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>  
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>  
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Create New Post | Go Blog with MongoDB<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.tailwindcss.com"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>  
<span class="hljs-tag">&lt;<span class="hljs-name">body</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-gray-100 min-h-screen"</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container mx-auto px-4 py-8"</span>&gt;</span>  
        <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-8"</span>&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-3xl font-bold text-center text-blue-600"</span>&gt;</span>Go Blog with MongoDB<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex justify-center mt-4"</span>&gt;</span>  
                <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded"</span>&gt;</span>Back to Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>  
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
        <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"max-w-2xl mx-auto bg-white rounded-lg shadow-md overflow-hidden"</span>&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"p-6"</span>&gt;</span>  
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-2xl font-bold mb-6 text-gray-800"</span>&gt;</span>Create New Post<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>  

                <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">"/save"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span>&gt;</span>  
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-4"</span>&gt;</span>  
                        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"title"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"block text-gray-700 font-medium mb-2"</span>&gt;</span>Title<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>  
                        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"title"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"title"</span> <span class="hljs-attr">required</span>  
                            <span class="hljs-attr">class</span>=<span class="hljs-string">"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"</span>&gt;</span>  
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  

                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-6"</span>&gt;</span>  
                        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"content"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"block text-gray-700 font-medium mb-2"</span>&gt;</span>Content<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>  
                        <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"content"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"content"</span> <span class="hljs-attr">rows</span>=<span class="hljs-string">"10"</span> <span class="hljs-attr">required</span>  
                            <span class="hljs-attr">class</span>=<span class="hljs-string">"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>  
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  

                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex justify-end"</span>&gt;</span>  
                        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-blue-500 hover:bg-blue-600 text-white px-6 py-2 rounded-md"</span>&gt;</span>  
                            Save Post  
                        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>  
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
                <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>  
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>This template allows you to create a new post.</p>
<h4 id="heading-edithtml">edit.html:</h4>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>  
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>  
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Edit Post | Go Blog with MongoDB<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.tailwindcss.com"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>  
<span class="hljs-tag">&lt;<span class="hljs-name">body</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-gray-100 min-h-screen"</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container mx-auto px-4 py-8"</span>&gt;</span>  
        <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-8"</span>&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-3xl font-bold text-center text-blue-600"</span>&gt;</span>Go Blog with MongoDB<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex justify-center mt-4"</span>&gt;</span>  
                <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded"</span>&gt;</span>Back to Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>  
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
        <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"max-w-2xl mx-auto bg-white rounded-lg shadow-md overflow-hidden"</span>&gt;</span>  
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"p-6"</span>&gt;</span>  
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-2xl font-bold mb-6 text-gray-800"</span>&gt;</span>Edit Post<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>  

                <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">"/save"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span>&gt;</span>  
                    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"id"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"{{.ID.Hex}}"</span>&gt;</span>  

                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-4"</span>&gt;</span>  
                        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"title"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"block text-gray-700 font-medium mb-2"</span>&gt;</span>Title<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>  
                        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"title"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"title"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"{{.Title}}"</span> <span class="hljs-attr">required</span>  
                            <span class="hljs-attr">class</span>=<span class="hljs-string">"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"</span>&gt;</span>  
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  

                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-6"</span>&gt;</span>  
                        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"content"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"block text-gray-700 font-medium mb-2"</span>&gt;</span>Content<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>  
                        <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"content"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"content"</span> <span class="hljs-attr">rows</span>=<span class="hljs-string">"10"</span> <span class="hljs-attr">required</span>  
                            <span class="hljs-attr">class</span>=<span class="hljs-string">"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"</span>&gt;</span>{{.Content}}<span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>  
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  

                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex justify-between"</span>&gt;</span>  
                        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/post/{{.ID.Hex}}"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-gray-600 hover:text-gray-800"</span>&gt;</span>Cancel<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>  
                        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-blue-500 hover:bg-blue-600 text-white px-6 py-2 rounded-md"</span>&gt;</span>  
                            Update Post  
                        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>  
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
                <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>  
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>This template is used to edit a post.</p>
<h3 id="heading-create-the-handlers">Create the handlers</h3>
<p>Next, set up the handlers to connect with MongoDB and render the templates. Create a new folder called <code>handlers</code> in your project's root directory, then add a <code>main.go</code> file inside it and insert the following code snippet:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> handlers

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"context"</span>
    <span class="hljs-string">"log"</span>
    <span class="hljs-string">"net/http"</span>
    <span class="hljs-string">"time"</span>

    <span class="hljs-string">"github.com/gin-gonic/gin"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/bson"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/bson/primitive"</span>
    <span class="hljs-string">"go.mongodb.org/mongo-driver/mongo"</span>
)

<span class="hljs-keyword">type</span> Post <span class="hljs-keyword">struct</span> {
    ID        primitive.ObjectID <span class="hljs-string">`bson:"_id,omitempty" json:"id"`</span>
    Title     <span class="hljs-keyword">string</span>             <span class="hljs-string">`bson:"title" json:"title"`</span>
    Content   <span class="hljs-keyword">string</span>             <span class="hljs-string">`bson:"content" json:"content"`</span>
    CreatedAt time.Time          <span class="hljs-string">`bson:"created_at" json:"created_at"`</span>
    UpdatedAt time.Time          <span class="hljs-string">`bson:"updated_at" json:"updated_at"`</span>
}

<span class="hljs-keyword">type</span> Handler <span class="hljs-keyword">struct</span> {
    db         *mongo.Database
    collection *mongo.Collection
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">NewHandler</span><span class="hljs-params">(db *mongo.Database)</span> *<span class="hljs-title">Handler</span></span> {
    <span class="hljs-keyword">return</span> &amp;Handler{
        db:         db,
        collection: db.Collection(<span class="hljs-string">"posts"</span>),
    }
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(h *Handler)</span> <span class="hljs-title">HomePage</span><span class="hljs-params">(c *gin.Context)</span></span> {
    ctx, cancel := context.WithTimeout(context.Background(), <span class="hljs-number">5</span>*time.Second)
    <span class="hljs-keyword">defer</span> cancel()

    cursor, err := h.collection.Find(ctx, bson.M{})
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        c.JSON(http.StatusInternalServerError, gin.H{<span class="hljs-string">"error"</span>: err.Error()})
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-keyword">defer</span> cursor.Close(ctx)

    <span class="hljs-keyword">var</span> posts []Post
    <span class="hljs-keyword">if</span> err = cursor.All(ctx, &amp;posts); err != <span class="hljs-literal">nil</span> {
        c.JSON(http.StatusInternalServerError, gin.H{<span class="hljs-string">"error"</span>: err.Error()})
        <span class="hljs-keyword">return</span>
    }

    c.HTML(http.StatusOK, <span class="hljs-string">"index.html"</span>, posts)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(h *Handler)</span> <span class="hljs-title">ViewPost</span><span class="hljs-params">(c *gin.Context)</span></span> {
    id := c.Param(<span class="hljs-string">"id"</span>)
    objID, err := primitive.ObjectIDFromHex(id)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        c.JSON(http.StatusBadRequest, gin.H{<span class="hljs-string">"error"</span>: <span class="hljs-string">"Invalid post ID"</span>})
        <span class="hljs-keyword">return</span>
    }

    ctx, cancel := context.WithTimeout(context.Background(), <span class="hljs-number">5</span>*time.Second)
    <span class="hljs-keyword">defer</span> cancel()

    <span class="hljs-keyword">var</span> post Post
    err = h.collection.FindOne(ctx, bson.M{<span class="hljs-string">"_id"</span>: objID}).Decode(&amp;post)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        c.JSON(http.StatusNotFound, gin.H{<span class="hljs-string">"error"</span>: <span class="hljs-string">"Post not found"</span>})
        <span class="hljs-keyword">return</span>
    }

    c.HTML(http.StatusOK, <span class="hljs-string">"post.html"</span>, post)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(h *Handler)</span> <span class="hljs-title">CreatePost</span><span class="hljs-params">(c *gin.Context)</span></span> {
    c.HTML(http.StatusOK, <span class="hljs-string">"create.html"</span>, <span class="hljs-literal">nil</span>)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(h *Handler)</span> <span class="hljs-title">EditPost</span><span class="hljs-params">(c *gin.Context)</span></span> {
    id := c.Param(<span class="hljs-string">"id"</span>)
    objID, err := primitive.ObjectIDFromHex(id)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        c.JSON(http.StatusBadRequest, gin.H{<span class="hljs-string">"error"</span>: <span class="hljs-string">"Invalid post ID"</span>})
        <span class="hljs-keyword">return</span>
    }

    ctx, cancel := context.WithTimeout(context.Background(), <span class="hljs-number">5</span>*time.Second)
    <span class="hljs-keyword">defer</span> cancel()

    <span class="hljs-keyword">var</span> post Post
    err = h.collection.FindOne(ctx, bson.M{<span class="hljs-string">"_id"</span>: objID}).Decode(&amp;post)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        c.JSON(http.StatusNotFound, gin.H{<span class="hljs-string">"error"</span>: <span class="hljs-string">"Post not found"</span>})
        <span class="hljs-keyword">return</span>
    }

    c.HTML(http.StatusOK, <span class="hljs-string">"edit.html"</span>, post)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(h *Handler)</span> <span class="hljs-title">SavePost</span><span class="hljs-params">(c *gin.Context)</span></span> {
    ctx, cancel := context.WithTimeout(context.Background(), <span class="hljs-number">5</span>*time.Second)
    <span class="hljs-keyword">defer</span> cancel()

    id := c.PostForm(<span class="hljs-string">"id"</span>)
    title := c.PostForm(<span class="hljs-string">"title"</span>)
    content := c.PostForm(<span class="hljs-string">"content"</span>)

    now := time.Now()

    <span class="hljs-keyword">if</span> id == <span class="hljs-string">""</span> {
        post := Post{
            Title:     title,
            Content:   content,
            CreatedAt: now,
            UpdatedAt: now,
        }

        result, err := h.collection.InsertOne(ctx, post)
        <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
            c.JSON(http.StatusInternalServerError, gin.H{<span class="hljs-string">"error"</span>: err.Error()})
            <span class="hljs-keyword">return</span>
        }

        log.Printf(<span class="hljs-string">"Created post with ID: %v\n"</span>, result.InsertedID)
    } <span class="hljs-keyword">else</span> {
        objID, err := primitive.ObjectIDFromHex(id)
        <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
            c.JSON(http.StatusBadRequest, gin.H{<span class="hljs-string">"error"</span>: <span class="hljs-string">"Invalid post ID"</span>})
            <span class="hljs-keyword">return</span>
        }

        update := bson.M{
            <span class="hljs-string">"$set"</span>: bson.M{
                <span class="hljs-string">"title"</span>:      title,
                <span class="hljs-string">"content"</span>:    content,
                <span class="hljs-string">"updated_at"</span>: now,
            },
        }

        result, err := h.collection.UpdateOne(ctx, bson.M{<span class="hljs-string">"_id"</span>: objID}, update)
        <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
            c.JSON(http.StatusInternalServerError, gin.H{<span class="hljs-string">"error"</span>: err.Error()})
            <span class="hljs-keyword">return</span>
        }

        log.Printf(<span class="hljs-string">"Updated post with ID: %s (Modified %d documents)\n"</span>, id, result.ModifiedCount)
    }

    c.Redirect(http.StatusSeeOther, <span class="hljs-string">"/"</span>)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(h *Handler)</span> <span class="hljs-title">DeletePost</span><span class="hljs-params">(c *gin.Context)</span></span> {
    id := c.Param(<span class="hljs-string">"id"</span>)
    objID, err := primitive.ObjectIDFromHex(id)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        c.JSON(http.StatusBadRequest, gin.H{<span class="hljs-string">"error"</span>: <span class="hljs-string">"Invalid post ID"</span>})
        <span class="hljs-keyword">return</span>
    }

    ctx, cancel := context.WithTimeout(context.Background(), <span class="hljs-number">5</span>*time.Second)
    <span class="hljs-keyword">defer</span> cancel()

    result, err := h.collection.DeleteOne(ctx, bson.M{<span class="hljs-string">"_id"</span>: objID})
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        c.JSON(http.StatusInternalServerError, gin.H{<span class="hljs-string">"error"</span>: err.Error()})
        <span class="hljs-keyword">return</span>
    }

    log.Printf(<span class="hljs-string">"Deleted %d document(s) with ID: %s\n"</span>, result.DeletedCount, id)
    c.Redirect(http.StatusSeeOther, <span class="hljs-string">"/"</span>)
}
</code></pre>
<p>The code above contains all the logic for managing blog posts. Here's what each component does:</p>
<ul>
<li><p><strong>Post struct:</strong> Defines the structure of a blog post document with fields for ID, title, content, and timestamps. The <code>bson</code> tags specify how fields are stored in MongoDB, while <code>json</code> tags handle JSON serialization.</p>
</li>
<li><p><strong>Handler struct:</strong> Contains a reference to the MongoDB database and the posts collection, providing a centralized way to access the database throughout your handlers.</p>
</li>
<li><p><strong>NewHandler function</strong>: Creates and initializes a new handler instance with the database connection and sets up the posts collection reference.</p>
</li>
<li><p><strong>HomePage:</strong> Retrieves all blog posts from the database using <code>Find()</code> with an empty filter and renders them using the <code>index.html</code> template.</p>
</li>
<li><p><strong>ViewPost:</strong> Fetches a single post by its ObjectID using <code>FindOne()</code> and displays it with the <code>post.html</code> template.</p>
</li>
<li><p><strong>CreatePost &amp; EditPost:</strong> Render the respective forms for creating new posts or editing existing ones.</p>
</li>
<li><p><strong>SavePost:</strong> Handles both creating new posts and updating existing ones. It checks if an ID is provided. If not, it creates a new post using <code>InsertOne()</code>. Otherwise, it updates the existing post using <code>UpdateOne()</code> with MongoDB's <code>$set</code> operator.</p>
</li>
<li><p><strong>DeletePost:</strong> Removes a post from the database using <code>DeleteOne()</code> and redirects back to the homepage.</p>
</li>
</ul>
<h3 id="heading-run-the-application">Run the application</h3>
<p>With everything set up, you can now launch your blog. Open your terminal and run:</p>
<pre><code class="lang-bash">go mod tidy &amp;&amp; go run main.go
</code></pre>
<p>Then, visit <a target="_blank" href="http://localhost:8080">http://localhost:8080</a> in your browser to see your blog in action.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753561817087/0e48d3d1-a6c0-4c5d-9245-cd6e86cd8596.png" alt="Blog management interface with a header &quot;Go Blog with MongoDB&quot; and a &quot;Create New Post&quot; button. Two blog post entries are shown with options to edit or delete." class="image--center mx-auto" width="512" height="283" loading="lazy"></p>
<h2 id="heading-thats-how-to-use-mongodb-with-go">That's How to Use MongoDB with Go</h2>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>Cheers to building more with Go and MongoDB!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
