Files
build-web-application-with-…/ru/04.1.md
Slava Zgordan 7f993ce880 04.1
2015-09-21 11:28:19 +02:00

6.6 KiB
Raw Blame History

4.1 Работа с формами

Перед тем, как начать, давайте посмотрим на простой пример обычной пользовательской формы, сохраненной как login.gtpl в папке Вашего проекта:

<html>
<head>
<title></title>
</head>
<body>
<form action="/login" method="post">
	Имя пользователя:<input type="text" name="username">
	Пароль:<input type="password" name="password">
	<input type="submit" value="Войти">
</form>
</body>
</html>

Эта форма отправит данные по адресу /login на сервер. После того, как пользователь нажем кнопку "Войти", дата будет послана на хэндлер login, зарегистрированный маршрутизатором сервера. Нам нужно знать, какой метод используется при этом - POST или GET?

Это легко узнать при помощи пакета http. Давайте посмотрим, как обработать данные формы со страницы входа:

package main

import (
	"fmt"
	"html/template"
	"log"
	"net/http"
	"strings"
)

func sayhelloName(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()  //Анализирует переданные параметры url, затем анализирует пакет ответа для тела POST (тела запроса)
	// внимание: без вызова метода ParseForm послежующие данные не будут получены
	fmt.Println(r.Form) // печатает информацию на сервере.
	fmt.Println("Путь: ", r.URL.Path)
	fmt.Println("Схема: ", r.URL.Scheme)
	fmt.Println(r.Form["url_long"])
	for k, v := range r.Form {
		fmt.Println("Ключ: ", k)
		fmt.Println("Значение: ", strings.Join(v, ""))
	}
	fmt.Fprintf(w, "Привет astaxie!") // пишет данные в ответ
}

func login(w http.ResponseWriter, r *http.Request) {
	fmt.Println("Метод:", r.Method) //получаем информацию о методе запроса
	if r.Method == "GET" {
		t, _ := template.ParseFiles("login.gtpl")
		t.Execute(w, nil)
	} else {
		r.ParseForm()
		// логическая часть процесса входа
		fmt.Println("Пользователь:", r.Form["username"])
		fmt.Println("Пароль:", r.Form["password"])
	}
}
	
func main() {
	http.HandleFunc("/", sayhelloName) // устанавливаем правило маршрутизатора
	http.HandleFunc("/login", login)
	err := http.ListenAndServe(":9090", nil) // устанавливаем порт для прослушивания
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

Здесь мы используем r.Method для того, чтобы получить информацию о методе запроса, и нам возвращается метод HTTP -"GET", "POST", "PUT" и т.д.

В функции login мы использовали метод r.Method, чтобы проверить, это страница входа или логика обработки информации о входе. Другими словами, мы проверяем, открыл ли пользователь страницу или уже пытается войти. Сервер отображает страницу только в случае, если запрос идет посредством метода GET, и запускает логику обработки информации о входе, если запрос использует метод POST.

Вы должны увидеть следующий интерфейс после открытия http://127.0.0.1:9090/login в броузере:

Рисунок 4.1 Интерфейс входа пользователя

Сервер ничего не напечатает, пока мы не введем имя пользователя и пароль, потому что хэндлер не будет анализировать данные, пока мы не вызовем r.ParseForm(). Давайте добавим r.ParseForm() перед fmt.Println("username:", r.Form["username"]), скомпилируем программу и вновь протестируем её. Вы обнаружите, что в этом случае информация стала печататься на стороне сервера.

r.Form contains all of the request arguments, for instance the query-string in the URL and the data in POST and PUT. If the data has conflicts, for example parameters that have the same name, the server will save the data into a slice with multiple values. The Go documentation states that Go will save the data from GET and POST requests in different places. r.Form содержит все аргументы запроса, например, сторку запроса в URL и данные в POST и PUT. Если в данных есть конфликты, например, параметры имеют одинаковое имя, сервер сохранит данные в срез из множества значений. Документация Go говорит о том, что Go сохраняет данные из запросов GET и POST в разных местах.

Try changing the value of the action in the form http://127.0.0.1:9090/login to http://127.0.0.1:9090/login?username=astaxie in the login.gtpl file, test it again, and you will see that the slice is printed on the server side.

Figure 4.2 Server prints request data

The type of request.Form is url.Value. It saves data with the format key=value.

v := url.Values{}
v.Set("name", "Ava")
v.Add("friend", "Jess")
v.Add("friend", "Sarah")
v.Add("friend", "Zoe")
// v.Encode() == "name=Ava&friend=Jess&friend=Sarah&friend=Zoe"
fmt.Println(v.Get("name"))
fmt.Println(v.Get("friend"))
fmt.Println(v["friend"])

Tips Requests have the ability to access form data using the FormValue() method. For example, you can change r.Form["username"] to r.FormValue("username"), and Go calls r.ParseForm automatically. Notice that it returns the first value if there are arguments with the same name, and it returns an empty string if there is no such argument.