I have been reading about context and passing values in middlewares. Since the julienschmidt httprouter is not compatible with http.Handler interface I thought I could save the httprouter Params
which is a slice of Param
https://godoc.org/github.com/julienschmidt/httprouter#Params
and save this in a context value and retrieve later.
The Go blog article on context: https://blog.golang.org/context says that:
Value allows a Context to carry request-scoped data. That data must be safe for simultaneous use by multiple goroutines.
I don't know if this data is safe. Slices are not thread safe as I understand, but how would multiple go routines access the data in this situation?
I have a handler that converts http.Handler to httprouter.Handle and saves the httprouter.Params so that I can use those params in http.HandlerFunc type functions.
type ctxKey string
var paramKey ctxKey = "params"
func paramHandler(h http.Handler) httprouter.Handle {
return httprouter.Handle(func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
ctx := context.WithValue(r.Context(), paramKey, ps)
h.ServeHTTP(w, r.WithContext(ctx))
})
}
var mutex sync.RWMutex
func params(r *http.Request) httprouter.Params {
// https://blog.golang.org/context
// "Value allows a Context to carry request-scoped data.
// That data must be safe for simultaneous use by multiple goroutines."
mutex.RLock()
value := r.Context().Value(paramKey)
mutex.RUnlock()
if ps, ok := value.(httprouter.Params); ok {
return ps
}
return httprouter.Params{}
}
In paramHandler I set the context value which is a slice of httprouter.Param, and in params(r *http.Request) function I receive the parameters.
My question is, do I need write locks when saving the slice of params in context in paramHandler, and read locks when retrieving the params from context as I have in the function param(*http.Request)?
I plan on retrieving the params like this:
func getUser(w http.ResponseWriter, r *http.Request) {
ps := params(r)
fmt.Println(ps.ByName("id"))
}
Are the locks necessary?