Navigating through routes and methods

The HTTP method used is stored in the Request.Method field. This field can be used inside a handler to have different behaviors for each supported method:

switch r.Method {
case http.MethodGet:
// GET implementation
case http.MethodPost:
// POST implementation
default:
http.NotFound(w, r)
}

The advantage of the http.Handler interface is that we can define our custom types. This can make the code more readable and can generalize this method-specific behavior:

type methodHandler map[string]http.Handler

func (m methodHandler) ServeHTTP(w http.ResponseWriter, r
*http.Request) {
h, ok := m[strings.ToUpper(r.Method)]
if !ok {
http.NotFound(w, r)
return
}
h.ServeHTTP(w, r)
}

This will make the code much more readable, and it will be reusable for different paths:

func main() {
http.HandleFunc("/path1", methodHandler{
http.MethodGet: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Showing record")
}),
http.MethodPost: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Updated record")
}),
})
if err := http.ListenAndServe(":3000", nil); err != nil {
log.Fatal(err)
}
}