通过一个http.ResponseWriter发送很少的响应

after I click on post button on frontend I receive data to my handler, create email and send it, but I want to inform user about status of email(sended or not) and redirect it back to main page. Problem is that I dont know how to pass alert and redirecting to main page at once.

Here is a handler code:

func contactHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method == http.MethodPost {
        r.ParseForm()
        /* creating email */
        err := smtp.SendMail("smtp.gmail.com:587", smtp.PlainAuth("", *emailFromLogin, *emailFromPassword, "smtp.gmail.com"), *emailFrom, []string{*emailTo}, []byte(msg))
        http.Redirect(w, r, "/", http.StatusMovedPermanently)
    }
}

That what I want send to user before redirecting.

if err != nil {
    fmt.Fprint(w, "<script>Email didn't send<script>")
} else {
    fmt.Fprint(w, "<script>Email sent successfully<script>")
}

You can't send data back with a redirect request, so here are 2 proposed alternatives.

Client side navigation

One option would be to send back a normal response with the message you want to show to the user, optionally with the URL to move to. After this, the client may do the navigation.

This may be an AJAX request, and client side JavaScript can process the result, and act upon it: display the message, and navigate. Here are some ways for client side JavaScript navigation:

window.location = "http://new-website.com";
window.location.href = "http://new-website.com";
window.location.assign("http://new-website.com");
window.location.replace("http://new-website.com");

Encode message in URL as parameter

Another common way is to send a redirect, and encode the message in the new URL as a query parameter, such as:

newPath := "/?msg=Hello"

This is a simple example, but if the message is more complex, you have to escape it to get a valid path. For that, you may use url.QueryEscape() like this:

msg := "Email didn't send"
path := "/?msg=" + url.QueryEscape(msg)

This would result in a path /?msg=Email+didn%27t+send (try it on the Go Playground). Another option would be to use url.URL and url.Values to assemble the URL, for example:

values := url.Values{}
values.Add("msg", "Email didn't send")

url := &url.URL{
    Path:     "/",
    RawQuery: values.Encode(),
}

fmt.Println(url)

The above prints (try it on the Go Playground):

/?msg=Email+didn%27t+send

Of course, the new page must handle that query parameter, e.g. use JavaScript to detect if in this case the msg query param exists, and if so, display it somehow to the user.

Also note that you shouldn't use the StatusMovedPermanently code for this redirect, as that may be cached by browsers and proxies. Instead use StatusFound. This status code indicates to clients that the redirection is temporary and may change in the future, so if the client needs the original URL again, it will query the original again (and not the new one automatically).