Greeting from newbie gopher!
I've got the following mux router setup:
s.router.HandleFunc("/test", s.TestHandler())
s.TestHandler:
func (s *server) TestHandler() http.HandlerFunc {
rnd := rand.Intn(100)
response := struct {
RND int `json:"rnd"`
}{
rnd,
}
return func(w http.ResponseWriter, r *http.Request) {
s.respond(w, r, 200, response)
return
}
}
Helper method s.respond:
func (s *server) respond(w http.ResponseWriter, r *http.Request, code int, data interface{}) {
w.WriteHeader(code)
if data != nil {
json.NewEncoder(w).Encode(data)
}
}
The issue is when I issue GET /test, I see the same number unless app is restarted.
I'm certain I'm doing something wrong, would appreciate if someone please point out my fault.
Function literals are closures: they may refer to variables defined in a surrounding function. Those variables are then shared between the surrounding function and the function literal, and they survive as long as they are accessible.
TestHandler()
generates a single random value and then returns a function literal, i.e. a closure, that uses this already generated value to send a response whenever it is executed by the router.
But, the surrounding function of a closure will not be, and has no reason to be, executed together with the closure whenever the closure is invoked. The surrounding function is executed only when it itself is invoked, like when you're registering the handler in s.router.HandleFunc("/test", s.TestHandler())
for example.
So, in the provided code, the rand.Intn
function in your TestHandler
is called exactly once, it is not called, as you seem to believe, every time you hit the server with a request.
To fix this just move the random-value-generating code a level below:
func (s *server) TestHandler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
rnd := rand.Intn(100)
response := struct {
RND int `json:"rnd"`
}{
rnd,
}
s.respond(w, r, 200, response)
}
}