簡體   English   中英

在GO中的http處理程序函數之間傳遞數據

[英]Passing data between http handler functions in GO

我有一個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寄存器()? 是否可以在r * http.Request中添加某種結構,以便在調用http.Redirect()時將其傳遞給func register()?

在您的示例中,如果您的表單提交被定向到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()函數,但是表單submit必須指向與你的寄存器頁面相同的路徑(例如/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
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM