Henrique Dias Henrique Dias - 20 days ago 5
HTTP Question

Go: use different handlers or inject variables into request Context?

I have an Handler like this:

type handler struct {
Services *domain.Services
Config *domain.Config
}


And then, a lot of new types (they can be twenty or more), like this:

type Handler1 handler
type Handler2 handler


And each one has a
ServeHTTP
method. And I use this so they can access the Services and Config variables.

They are being used in routes like this:

r.Handle("/login", &h.Handler1{
Services: s,
Config: c,
})


My question is: should I create all of this structs or just create a function that injects the Services and Config into the request Context and then I access them using
r.Context().Value()
?

I thought about doing this:

func handler1(w http.ResponseWriter, r *http.Request) {
s, c := r.Context().Value("services"), r.Context().Value("config")
// My code
}

r.HandleFunc("/login", inject(handler1, s, c))


What's the best/recommended?

Answer

As an alternative to creating all these handler types, you can have functions which return other functions (http.HandlerFunc). This way, you will create a closure and can access the parameters when the request arrives in the handler. For example:

package main

import (
    "fmt"
    "net/http"
)

func SomeHandler(conf SomeConfig, service SomeService) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "foobar config: %q", conf)
    }
}

func main() {
    // TODO: initialise your conf & service
    http.HandleFunc("/somepath", SomeHandler(conf, service))
}
Comments