liveBook · Manning

Routing

As explained in Go in Practice, Second Edition

URL pattern matching is the routing of requests by applying expressive patterns to URL paths rather than only comparing fixed path segments.

Routing maps an incoming HTTP request to the handler that produces its response. A single handler can serve a small application, but separate handlers make distinct paths and HTTP methods easier to manage as a server grows. In Go, net/http supplies the standard starting point. section 2.3 section 2.3.3

Choose a pattern according to what distinguishes the requests:

  • For a few fixed paths, register a handler for each path with http.HandleFunc or a ServeMux. A trailing-slash pattern can also cover paths beneath it; the handler may then need to inspect the remaining path. section 2.3.3
  • For one path with different operations, include the HTTP method in the pattern, such as GET /comments and POST /comments. A wrapper handler can inspect request attributes when registration patterns do not provide enough control. section 8.1.1
  • For an identifier in the URL, register a variable pattern such as GET /comments/{id}, read it with r.PathValue("id"), and validate it before using it. section 8.2
  • For separate areas of an application, mount ServeMux instances beneath path prefixes. More elaborate matching can instead use a custom regular-expression resolver; consider that added machinery only when simpler patterns do not fit. section 8.2 section 2.3.3

One endpoint, two methods, one path value

A comments API can send GET /comments to a list handler and POST /comments to a creation handler. Register GET /comments/{id} separately for an individual comment. That handler reads r.PathValue("id"), converts it to a number, and returns a not-found response when the requested comment does not exist. The method and path together determine which handler runs; the variable supplies data to that handler. section 8.1.1 section 8.2

Listing 8.7 Extracting information from request path
func getComment(w http.ResponseWriter, r *http.Request) {
    commentID, err := strconv.Atoi(r.PathValue("id"))       #1
    if err != nil {                                    #2
        w.WriteHeader(http.StatusInternalServerError)
        return
    }
    if commentID == 0 || len(comments) < commentID {     #3
        w.WriteHeader(http.StatusNotFound)
        return
    }
    fmt.Fprintf(w, "Comment %d: %s", commentID, 
    comments[commentID-1].text)                                     #4
}

func main() {
    http.HandleFunc("GET /comments", getComments)
    http.HandleFunc("GET /comments/{id}", getComment)     #5
    http.HandleFunc("POST /comments", postComments)

    if err := http.ListenAndServe(":8000", nil); err != nil {
        panic(err)
    }
}

The handler registration and r.PathValue("id") call show how a variable path pattern reaches a specific comment handler. section 8.2

How Go in Practice, Second Edition covers it

How deep it goes
Works through handler registration, method patterns, path extraction, nested multiplexers, and a custom regex alternative without requiring a framework.
Examples
Uses GET and POST comment handlers, an individual-comment path variable, and nested user and comment routers.
What it assumes
Assumes basic Go functions and HTTP requests while demonstrating how to register handlers and extract path values.
What you can do after
Build it from scratch with net/http handler patterns and PathValue, or extend routing with nested multiplexers.
How it connects
Connects routing to HTTP methods, REST APIs, ServeMux, path variables, and handler functions.

Also explained in

Compare how 22 books explain routing →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go in Practice, Second Edition. The section links point to the parts of the book it draws on.