SyntaxStudy
Sign Up
Go Building an HTTP Server with net/http
Go Beginner 1 min read

Building an HTTP Server with net/http

Go's standard library includes a production-quality HTTP server in the `net/http` package. A minimal server can be started with just a few lines: define handler functions, register them with a multiplexer (ServeMux), and call `http.ListenAndServe`. The handler function receives a `http.ResponseWriter` to write the response and an `*http.Request` containing all request data. The `http.Handler` interface has a single method `ServeHTTP(ResponseWriter, *Request)`. Any type implementing this interface can be registered as a handler. The `http.HandlerFunc` type is a function adapter that converts an ordinary function into an `http.Handler`, enabling the use of plain functions as handlers without defining a full type. Go 1.22 enhanced the default ServeMux with method-based routing and path parameters. Routes can now be declared as `"GET /users/{id}"` and the `{id}` parameter extracted with `r.PathValue("id")`. For more complex routing needs, third-party routers like `chi` or `gorilla/mux` are popular choices that build on the same `http.Handler` interface.
Example
package main

import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "strconv"
)

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
}

var users = []User{
    {1, "Alice"},
    {2, "Bob"},
    {3, "Carol"},
}

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

func getUser(w http.ResponseWriter, r *http.Request) {
    idStr := r.PathValue("id") // Go 1.22+
    id, err := strconv.Atoi(idStr)
    if err != nil {
        http.Error(w, "invalid id", http.StatusBadRequest)
        return
    }
    for _, u := range users {
        if u.ID == id {
            w.Header().Set("Content-Type", "application/json")
            json.NewEncoder(w).Encode(u)
            return
        }
    }
    http.NotFound(w, r)
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("GET /users", listUsers)
    mux.HandleFunc("GET /users/{id}", getUser)
    mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, `{"status":"ok"}`)
    })

    addr := ":8080"
    log.Printf("listening on %s\n", addr)
    if err := http.ListenAndServe(addr, mux); err != nil {
        log.Fatal(err)
    }
}