Introduction: Why Go is Ideal for REST APIs?
Go (Golang) is a modern compiled programming language created at Google. It combines the high performance of C++ with the simplicity of Python. If you need to quickly write a REST API, Go is one of the best choices. In this article, we will create a full-fledged REST API in Go in 30 minutes, using only the standard library net/http. You will see how easy it is to handle HTTP requests, route them, and return JSON responses.
By the end of the article, you will be able to write your own API that can be deployed on a server. We will not use any third-party frameworks — only pure Go, which makes the code lightweight and fast.
Step 1: Installing Go and Creating a Project
Installing Go
If you don't have Go installed yet, download the latest version from the official website. Follow the instructions for your operating system. After installation, check the version in the terminal:
go versionYou should see something like go version go1.22.0 linux/amd64.
Creating a Project
Create a new directory for the project and initialize a Go module:
mkdir go-rest-apicd go-rest-apigo mod init go-rest-apiNow the project structure is ready. We will write all the code in a single file main.go to keep the example simple.
Step 2: Simple HTTP Server in Go
Let's start with a basic HTTP server. Open the file main.go and add the following code:
package main
import ( "fmt" "log" "net/http")
func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, REST API on Go!") })
log.Println("Server started on port 8080") log.Fatal(http.ListenAndServe(":8080", nil))}Start the server with the command go run main.go and open your browser at http://localhost:8080. You will see a welcome message. Congratulations — your first HTTP server in Go is running!
Code Breakdown
http.HandleFunc— registers a handler for the "/" route.http.ListenAndServe— starts the server on port 8080.log.Fatal— prints an error if the server fails to start.
Step 3: Adding Routing and JSON Handling
Now let's add support for REST style: GET, POST, PUT, DELETE. We will create a simple in-memory "database" (a slice of structs) and manage a list of tasks (todo list).
Data Structure
Add the Task struct description and a global slice to main.go:
type Task struct { ID int `json:"id"` Name string `json:"name"`}
var tasks []Taskvar nextID int = 1Route Handlers
Let's create a main handler that will analyze the HTTP method and call the appropriate function:
func tasksHandler(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: getTasks(w, r) case http.MethodPost: createTask(w, r) default: http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) }}
func taskHandler(w http.ResponseWriter, r *http.Request) { // Extract ID from URL idStr := strings.TrimPrefix(r.URL.Path, "/tasks/") id, err := strconv.Atoi(idStr) if err != nil { http.Error(w, "Invalid task ID", http.StatusBadRequest) return }
switch r.Method { case http.MethodGet: getTask(w, r, id) case http.MethodPut: updateTask(w, r, id) case http.MethodDelete: deleteTask(w, r, id) default: http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) }}