To be fair, Express is a web framework. Go's net/http package is a little lower level than that.
Still, this is possible if you make up for the lack of a framework by writing some code yourself. I'd use (and I do use) gorilla/context[1] to allow me to pass data in the request context between middleware layers (i.e. CSRF middleware passes the token along).
You could write a couple of little helpers using gorilla/context (SetUser/GetUser, or more generically, SetString/GetString) and SetUser(username, r) in your middleware. The helpers (see the context docs!) just wrap a type assertion on the Get side, and set a map value on the Set side.
// Compatible with http.HandlerFunc
func auth(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
SetUser(r, "dave")
h.ServeHTTP(w, r)
}
}
// Routes
r.HandleFunc("/admin", use(adminHandler, auth)
http.Handle("/", r)
// Allows you to chain your middleware rather than wrapping functions
func use(h http.HandlerFunc, middleware ...func(http.HandlerFunc) http.HandlerFunc) http.HandlerFunc {
for _, m := range middleware {
h = m(h)
}
return h
}
You can mod this to work with http.Handler if you want: replace HandlerFunc and then write r.Handle("/admin", use(http.HandlerFunc(adminHandler), auth) instead.
[1]: http://www.gorillatoolkit.org/pkg/context