【问题标题】:Passing data between http handler functions in GO在 GO 中的 http 处理函数之间传递数据
【发布时间】:2016-03-25 07:09:41
【问题描述】:

我有一个 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()?

【问题讨论】:

    标签: http go


    【解决方案1】:

    在您的示例中,如果您的表单提交被定向到 validate() 处理程序,该处理程序将发回 HTTP 响应(这将是一个重定向),浏览器将再次调用 /register。您的 validate() 处理程序和您的 register() 处理程序之间没有连接,*http.Request 值将与浏览器发出另一个 HTTP 请求不同,因此将创建另一个 *http.Request 值并在第二次调用时传递.

    您可以在重定向 URL 中指定参数,例如重定向到/register?someParam=someValue,但这只是不必要的往返,而且会使事情复杂化。

    一个更简单的解决方案是不分离表单渲染和验证(在处理程序级别)。同一个处理程序可以同时处理两者,因此不需要在两个处理程序之间共享数据。

    例子:

    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()函数,但表单提交仍然必须指向与你的注册页面相同的路径(例如/register):

    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
    }
    

    【讨论】:

    • 非常感谢 icza。在一个处理函数中做所有事情似乎是一种更优雅的解决方案。
    猜你喜欢
    • 2018-04-27
    • 2010-12-31
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多