Объявление и назначение обработчиков ServeMux в цикле не работает
У меня есть следующий фрагмент кода, и он не работает должным образом. В частности, все запросы к любым конечным точкам обрабатываются как запросы к/banana/auth
или/banana/description
конечные точки.
type Route struct {
AuthRoute string
DescriptionRoute string
}
var routes = [2]Route{
{
AuthRoute: "/apple/auth",
DescriptionRoute: "/apple/description",
},
{
AuthRoute: "/banana/auth",
DescriptionRoute: "/banana/description",
},
}
// ...
sm := http.NewServeMux()
for i, authServerConfig := range authServerConfigs {
authHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authServerConfig.Auth(w, r)
}
sm.Handle(routes[i].AuthRoute, authHandler)
descriptionHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authServerConfig.ServeDescription(w, r)
}
sm.Handle(routes[i].DescriptionRoute, descriptionHandler)
}
server := &http.Server{
// ...
Handler: sm,
// ...
}
server.ListenAndServe()
Когда я пошел дальше и заменил цикл for этими операторами, он работал именно так, как я хотел:
authHandlerApple := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authServerConfig.Auth(w, r)
}
sm.Handle(routes[0].AuthRoute, authHandlerApple)
descriptionHandlerApple := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authServerConfig.ServeDescription(w, r)
}
sm.Handle(routes[0].DescriptionRoute, descriptionHandlerApple)
authHandlerBanana := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authServerConfig.Auth(w, r)
}
sm.Handle(routes[1].AuthRoute, authHandlerBanana)
descriptionHandlerBanana := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authServerConfig.ServeDescription(w, r)
}
sm.Handle(routes[1].DescriptionRoute, descriptionHandlerBanana)
Вопрос в том, что я изначально делал не так и как мне избежать написания корявого кода, как во втором примере?
1 ответ
Согласно часто задаваемым вопросам - что происходит с замыканиями, работающими как горутины , каждое замыкание использует эту единственную переменную.authServerConfig
вfor
петля. Чтобы исправить это, просто добавьтеauthServerConfig := authServerConfig
в петле
for i, authServerConfig := range authServerConfigs {
authServerConfig := authServerConfig
authHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authServerConfig.Auth(w, r)
})
sm.Handle(routes[i].AuthRoute, authHandler)
descriptionHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authServerConfig.ServeDescription(w, r)
})
sm.Handle(routes[i].DescriptionRoute, descriptionHandler)
}