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

Mic*_*l C 1 go gorilla

来自新手地鼠的问候!

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

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
    }
}
Run Code Online (Sandbox Code Playgroud)

辅助方法 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

mko*_*iva 5

函数字面量

函数字面量是闭包:它们可以引用在周围函数中定义的变量。然后这些变量在周围的函数和函数字面量之间共享,只要它们可访问,它们就会存在。


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)
    }
}
Run Code Online (Sandbox Code Playgroud)