Building a CRUD API in Go

Previously, we built a simple task API that could create and retrieve tasks.

If you have been following this series, we’ve gradually progressed from building a simple HTTP server to creating a JSON-based task API. In this article, we will complete tha…


This content originally appeared on DEV Community and was authored by Steve Omollo

Previously, we built a simple task API that could create and retrieve tasks.

If you have been following this series, we've gradually progressed from building a simple HTTP server to creating a JSON-based task API. In this article, we will complete that progression by adding update and delete functionality, giving our API the four operations commonly known as CRUD.

CRUD stands for:

  • Create
  • Read
  • Update
  • Delete

These operations form the foundation of many backend applications and APIs.

In this tutorial, we will extend our task API using only Go's standard library. To keep things simple, we'll continue storing tasks in memory using a slice rather than a database.

By the end, you'll understand:

  • how CRUD APIs work
  • how to handle multiple HTTP methods
  • how to update existing data
  • how to remove data from slices
  • how backend APIs manage resources

Prerequisites

To follow along, you should have:

  • Go installed
  • basic familiarity with Go syntax
  • understanding of the net/http package
  • basic understanding of JSON handling

You can confirm if Go is installed by running:

go version

Step 1 — Create the Project

Create a new folder for the project:

mkdir go-crud-api
cd go-crud-api

Now initialize a Go module:

go mod init go-crud-api

Step 2 — Create the Server File

Create a file called main.go.

Your project structure should now look like this.

go-crud-api/
├─ go.mod
└─ main.go

Step 3 — Write the CRUD API

Open main.go and add the following code:

package main

import (
    "encoding/json"
    "net/http"
)

type Task struct {
    ID        int        `json:"id"`
    Title     string     `json:"title"`
}

var tasks []Task

func tasksHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")

    switch r.Method {

    case http.MethodGet:
        json.NewEncoder(w).Encode(tasks)

    case http.MethodPost:
        var task Task

        err := json.NewDecoder(r.Body).Decode(&task)
        if err != nil {
            http.Error(w, "Invalid JSON", http.StatusBadRequest)
            return
        }

        tasks = append(tasks, task)
        json.NewEncoder(w).Encode(task)

    case http.MethodPut:
        var updatedTask Task

        err := json.NewDecoder(r.Body).Decode(&updatedTask)
        if err != nil {
            http.Error(w, "Invalid JSON", http.StatusBadRequest)
            return
        }

        for i, task := range tasks {
            if task.ID == updatedTask.ID {
                tasks[i].Title = updatedTask.Title
                json.NewEncoder(w).Encode(tasks[i])
                return
            }
        }

        http.Error(w, "Task not found", http.StatusNotFound)

    case http.MethodDelete:
        var taskToDelete Task

        err := json.NewDecoder(r.Body).Decode(&taskToDelete)
        if err != nil {
            http.Error(w, "Invalid JSON", http.StatusBadRequest)
            return
        }

        for i, task := range tasks {
            if task.ID == taskToDelete.ID {
                tasks = append(tasks[:i], tasks[i+1:]...)
                w.Write([]byte("Task deleted"))
                return
            }
        }

        http.Error(w, "Task not found", http.StatusNotFound)

    default:
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
    }
}

func main() {
    http.HandleFunc("/tasks", tasksHandler)

    http.ListenAndServe(":8080", nil)
}

Now let's unpack what is happening.

Understanding CRUD Operations

CRUD represents the four most common actions performed on data.

Operation HTTP Method
Create POST
Read GET
Update PUT
Delete DELETE

Most backend APIs are built around these operations.

Create and Read

The POST and GET handlers work exactly as they did in the previous tutorial.

  • POST creates tasks
  • GET retrieves tasks

These operations allow us to add and view data.

Understanding Updates

This section handles updates:

case http.MethodPut:

The server expects updated task information in the request body.

For example:

{
    "id": 1,
    "title": "Learn Advanced Go"
}

After decoding the request, we search for a matching task:

for i, task := range tasks {
    if task.ID == updatedTask.ID {

If a match is found, we update the title:

tasks[i].Title = updatedTask.Title

Then we return the updated task as JSON.

Understanding Deletes

This section handles deleting tasks:

case http.MethodDelete:

The client sends the ID of the task to remove:

{
    "id": 1
}

We search for the task with matching ID and remove it from the slice.

The deletion happens here:

tasks = append(tasks[:i], tasks[i+1:]...)

This combines:

  • everything before the task
  • everything after the task

into a new slice that no longer contains the deleted item.

Understanding Slice Deletion

This line often looks strange at first:

tasks = append(tasks[:i], tasks[i+1:]...)

Let's break it down.

Suppose we have:

tasks = [1 2 3 4]

and want to remove:

2

Then:

tasks[:i]

gives:

[1]

and:

tasks[i+1:]

gives:

[3 4]

Appending them together creates:

[1 3 4]

The item has effectively been removed.

Go Tip: The append(tasks[:i], tasks[i+1:]...) pattern is one of the most common ways to remove an element from a slice in Go. You'll see it in many Go projects, so it's worth understanding how it works.

Step 4 — Run the Server

Start the application:

go run main.go

The server should now be running on port 8080.

Step 5 — Create a Task

curl -X POST http://localhost:8080/tasks \
-H "Content-Type: application/json" \
-d '{"id":1,"title":"Learn Go"}'

Response:

{
    "id": 1,
    "title": "Learn Go"
}

Step 6 — Retrieve Tasks

curl http://localhost:8080/tasks

Response:

[
    {
        "id": 1,
        "title": "Learn Go"
    }
]

Step 7 — Update a Task

curl -X PUT http://localhost:8080/tasks \
-H "Content-Type: application/json" \
-d '{"id":1,"title":"Learn Advanced Go"}'

Response:

{
    "id": 1,
    "title": "Learn Advanced Go"
}

Step 8 — Delete a Task

curl -X DELETE http://localhost:8080/tasks \
-H "Content-Type: application/json" \
-d '{"id":1}'

Response:

Task deleted

What Happens When a Request Is Made?

Here's the flow:

  1. The client sends an HTTP request.
  2. Go checks the request method.
  3. The appropriate handler creates, retrieves, updates, or deletes a task.
  4. The server prepares the response.
  5. A response is sent back to the client

This is the foundation of many real-world APIs.

Where to Go Next

Now that we have a simple CRUD API, we could extend it by adding:

  • route parameters
  • persistent databases
  • request validation
  • middleware
  • authentication

This is where backend applications begin moving closer to production-ready systems.

Final Thoughts

We started with a simple task API and extended it into a complete CRUD API.

Along the way, we learned about:

  • HTTP methods
  • updating data
  • deleting data
  • slice manipulation
  • API design

These concepts appear in countless backend applications and services.

Thanks for reading!

Happy coding!


This content originally appeared on DEV Community and was authored by Steve Omollo


Print Share Comment Cite Upload Translate Updates
APA

Steve Omollo | Sciencx (2026-07-16T08:32:48+00:00) Building a CRUD API in Go. Retrieved from https://www.scien.cx/2026/07/16/building-a-crud-api-in-go/

MLA
" » Building a CRUD API in Go." Steve Omollo | Sciencx - Thursday July 16, 2026, https://www.scien.cx/2026/07/16/building-a-crud-api-in-go/
HARVARD
Steve Omollo | Sciencx Thursday July 16, 2026 » Building a CRUD API in Go., viewed ,<https://www.scien.cx/2026/07/16/building-a-crud-api-in-go/>
VANCOUVER
Steve Omollo | Sciencx - » Building a CRUD API in Go. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2026/07/16/building-a-crud-api-in-go/
CHICAGO
" » Building a CRUD API in Go." Steve Omollo | Sciencx - Accessed . https://www.scien.cx/2026/07/16/building-a-crud-api-in-go/
IEEE
" » Building a CRUD API in Go." Steve Omollo | Sciencx [Online]. Available: https://www.scien.cx/2026/07/16/building-a-crud-api-in-go/. [Accessed: ]
rf:citation
» Building a CRUD API in Go | Steve Omollo | Sciencx | https://www.scien.cx/2026/07/16/building-a-crud-api-in-go/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.