我有一个 http 处理函数,只有当该电子邮件尚未被接收时,它才会将电子邮件保存到数据库中。如果电子邮件已被占用或某些其他数据无效,我想重定向回表单并通知用户发生错误的位置。
func validate(w http.ResponseWriter, r *http.Request) {
//query database to check if data r.FormValues were
//valid
//IF form values were not valid redirect back to the
//registration form and pass on data indicating the
//form data was not valid
{
http.Redirect(w, r, "/register", http.StatusFound)
}
}
究竟如何将数据从 func validate() 发送到 func register()?是否可以向 r* http.Request 添加某种结构,以便在调用 http.Redirect() 时将其传递给 func register()?
最佳答案
在您的示例中,如果您的表单提交定向到 validate()
处理程序,该处理程序将发回 HTTP 响应(这将是重定向),浏览器将再次调用 /注册
。您的 validate()
处理程序和您的 register()
处理程序之间没有连接,*http.Request
值将与浏览器发出另一个 HTTP 请求,因此将创建另一个 *http.Request
值并在第二次调用时传递。
您可以在重定向 URL 中指定参数,例如重定向到 /register?someParam=someValue
但这只是不必要的往返并且使事情复杂化。
一个更简单的解决方案是不分离表单呈现和验证(在处理程序级别)。同一个处理程序可以处理这两者,因此 2 个处理程序之间不需要共享数据。
例子:
func register(w http.ResponseWriter, r *http.Request) {
// Params for rendering the page
m := map[string]interface{}{}
// Is form submitted?
if r.FormValue("submitRegister") != "" {
// check submitted values
// E.g. check email, let's say it's already in use:
email := r.FormValue("Email")
if alreadyInUse {
m["Error"] = "Email already in use!"
}
if m["Error"] == "" {
// If all values are OK, create user, and redirect:
http.Redirect(w, r, "/home", http.StatusFound)
return // AND return!
}
// Store submitted values in params, so when we render
// the registration form again, we fill submitted params as initial values,
// so user don't have to fill everything again (expect maybe the password)
m["Email"] = email
}
// Either no submit or validation errors
// Render the registration form, using submitted values as initial ones
// Also if m["Error"] is set, render the error above the form
registerTempl.Execute(w, m)
}
当然你可以把它分解成函数,你可以有一个单独的 validate()
函数,但是表单提交仍然必须指向与你的注册页面相同的路径(例如 /注册
):
func register(w http.ResponseWriter, r *http.Request) {
// Params for rendering the page
m := map[string]interface{}{}
// Is form submitted?
if r.FormValue("submitRegister") != "" {
validate(w, r, m)
if m["Error"] == "" {
return // AND return!
}
}
// Either no submit or validation errors
// Render the registration form, using submitted values as initial ones
// Also if m["Error"] is set, render the error above the form
registerTempl.Execute(w, m)
}
func validate(w http.ResponseWriter, r *http.Request, m map[string]interface{}) {
// check submitted values
// E.g. check email, let's say it's already in use:
email := r.FormValue("Email")
if alreadyInUse {
m["Error"] = "Email already in use!"
}
if m["Error"] == "" {
// If all values are OK, create user, and redirect:
http.Redirect(w, r, "/home", http.StatusFound)
return
}
// Store submitted values in params, so when we
// render the registration form again, we fill submitted params as initial values,
// so user don't have to fill everything again (expect maybe the password)
m["Email"] = email
}
关于http - 在 GO 中的 http 处理函数之间传递数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36215571/