BudiBadu Logo

Samplebadu

Code with Example
BudiBadu Logo
Samplebadu

Go by Example: Building REST APIs

Go 1.23

Build a RESTful API in Go without external frameworks. This example demonstrates how to handle different HTTP methods (GET, POST), route requests, and work with JSON data using the standard library, providing a deep understanding of HTTP mechanics.

Code

package main

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

type Todo struct {
    ID    string `json:"id"`
    Title string `json:"title"`
    Done  bool   `json:"done"`
}

var todos = []Todo{
    {ID: "1", Title: "Learn Go", Done: false},
    {ID: "2", Title: "Build API", Done: false},
}

func getTodos(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(todos)
}

func createTodo(w http.ResponseWriter, r *http.Request) {
    var todo Todo
    _ = json.NewDecoder(r.Body).Decode(&todo)
    todos = append(todos, todo)
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(todo)
}

func main() {
    http.HandleFunc("/todos", func(w http.ResponseWriter, r *http.Request) {
        switch r.Method {
        case http.MethodGet:
            getTodos(w, r)
        case http.MethodPost:
            createTodo(w, r)
        default:
            http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        }
    })

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

Explanation

Building REST APIs in Go is straightforward with the standard library, especially with the routing enhancements in Go 1.22. A robust API typically involves routing, JSON handling, and proper status codes.

Key patterns for Go REST APIs:

  • Streaming JSON: Use json.NewEncoder(w).Encode(v) and json.NewDecoder(r.Body).Decode(&v). This streams data directly to/from the network connection, which is more memory-efficient than Marshal/Unmarshal for large payloads.
  • Method Routing: Use the new ServeMux patterns like "GET /todos/{id}" to handle different HTTP verbs cleanly without big switch statements.
  • Middleware: Wrap your handlers to add cross-cutting concerns like logging, CORS, and authentication (covered in the Middleware example).

Code Breakdown

9-11
Struct tags define how the Todo struct is serialized to JSON.
20
Setting the Content-Type header to application/json informs the client that the response body is JSON.
21
json.NewEncoder(w).Encode(todos) streams the JSON encoding of the 'todos' slice directly to the response writer.
26
json.NewDecoder(r.Body).Decode(&todo) reads the request body and unmarshals the JSON into the 'todo' struct.
34
We switch on r.Method to handle different HTTP verbs (GET vs POST) on the same endpoint.