为什么http.HandlerFunc总是返回相同的随机数

时间:2020-05-07 12:10:14

标签: go gorilla

新手gopher的问候!

我有以下多路复用器路由器设置:

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方法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)
    }
}

问题是当我发出GET / test时,除非重新启动应用程序,否则我看到的数字相同。

我确定我做错了,如果有人请指出我的错,我将不胜感激。

1 个答案:

答案 0 :(得分:5)

Function literals

函数文字是 closures :它们可以引用在中定义的变量 周围的功能。然后,这些变量将在 周围的函数和函数文字,它们作为 只要它们可以访问。


TestHandler()生成一个单个随机值,然后返回一个函数文字,即一个闭包,它使用已生成的 值,以便在路由器执行响应时发送响应。

但是,每次调用闭包时,闭包的周围函数都不会并且没有理由与闭包一起执行。环绕函数仅在自身被调用时才执行,例如在s.router.HandleFunc("/test", s.TestHandler())中注册处理程序时。

因此,在提供的代码中,rand.Intn中的TestHandler函数仅被调用一次,正如您似乎相信的那样,每次您通过请求访问服务器时都不会调用该函数。

要解决此问题,只需将生成随机值的代码移到下一级:

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)
    }
}