Merging other languages

This commit is contained in:
James Miranda
2016-09-23 18:01:10 -03:00
parent 380a8ee74c
commit de3c5bdaa4
490 changed files with 24539 additions and 24588 deletions

View File

@@ -1,109 +1,107 @@
# 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包里面有一个很简单的方式就可以获取我们在前面web的例子的基础上来看看怎么处理login页面的form数据
package main
import (
"fmt"
"html/template"
"log"
"net/http"
"strings"
)
func sayhelloName(w http.ResponseWriter, r *http.Request) {
r.ParseForm() //解析url传递的参数对于POST则解析响应包的主体request body
//注意:如果没有调用ParseForm方法下面无法获取表单的数据
fmt.Println(r.Form) //这些信息是输出到服务器端的打印信息
fmt.Println("path", r.URL.Path)
fmt.Println("scheme", r.URL.Scheme)
fmt.Println(r.Form["url_long"])
for k, v := range r.Form {
fmt.Println("key:", k)
fmt.Println("val:", strings.Join(v, ""))
}
fmt.Fprintf(w, "Hello astaxie!") //这个写入到w的是输出到客户端的
}
func login(w http.ResponseWriter, r *http.Request) {
fmt.Println("method:", r.Method) //获取请求的方法
if r.Method == "GET" {
t, _ := template.ParseFiles("login.gtpl")
log.Println(t.Execute(w, nil))
} else {
//请求的是登陆数据,那么执行登陆的逻辑判断
fmt.Println("username:", r.Form["username"])
fmt.Println("password:", 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`来完成的,这是个字符串类型的变量,返回GET, POST, PUT等method信息。
login函数中我们根据`r.Method`来判断是显示登录界面还是处理登录逻辑。当GET方式请求时显示登录界面其他方式请求时则处理登录逻辑如查询数据库、验证登录信息等。
当我们在浏览器里面打开`http://127.0.0.1:9090/login`的时候,出现如下界面
![](images/4.1.login.png?raw=true)
如果你看到一个空页面,可能是你写的 login.gtpl 文件中有错误,请根据控制台中的日志进行修复。
图4.1 用户登录界面
我们输入用户名和密码之后发现在服务器端是不会打印出来任何输出的为什么呢默认情况下Handler里面是不会自动解析form的必须显式的调用`r.ParseForm()`后,你才能对这个表单数据进行操作。我们修改一下代码,在`fmt.Println("username:", r.Form["username"])`之前加一行`r.ParseForm()`,重新编译,再次测试输入递交,现在是不是在服务器端有输出你的输入的用户名和密码了。
`r.Form`里面包含了所有请求的参数比如URL中query-string、POST的数据、PUT的数据所有当你在URL的query-string字段和POST冲突时会保存成一个slice里面存储了多个值Go官方文档中说在接下来的版本里面将会把POST、GET这些数据分离开来。
现在我们修改一下login.gtpl里面form的action值`http://127.0.0.1:9090/login`修改为`http://127.0.0.1:9090/login?username=astaxie`再次测试服务器的输出username是不是一个slice。服务器端的输出如下
![](images/4.1.slice.png?raw=true)
图4.2 服务器端打印接受到的信息
`request.Form`是一个url.Values类型里面存储的是对应的类似`key=value`的信息下面展示了可以对form数据进行的一些操作:
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**:
Request本身也提供了FormValue()函数来获取用户提交的参数。如r.Form["username"]也可写成r.FormValue("username")。调用r.FormValue时会自动调用r.ParseForm所以不必提前调用。r.FormValue只会返回同名参数中的第一个若参数不存在则返回空字符串。
## links
* [目录](<preface.md>)
* 上一节: [表单](<04.0.md>)
* 下一节: [验证表单的输入](<04.2.md>)
# 4.1 Process form inputs
Before we begin, let's take a look at a simple example of a typical user form, saved as `login.gtpl` in your project folder.
<html>
<head>
<title></title>
</head>
<body>
<form action="/login" method="post">
Username:<input type="text" name="username">
Password:<input type="password" name="password">
<input type="submit" value="Login">
</form>
</body>
</html>
This form will submit to `/login` on the server. After the user clicks the login button, the data will be sent to the `login` handler registered by the server router. Then we need to know whether it uses the POST method or GET.
This is easy to find out using the `http` package. Let's see how to handle the form data on the login page.
package main
import (
"fmt"
"html/template"
"log"
"net/http"
"strings"
)
func sayhelloName(w http.ResponseWriter, r *http.Request) {
r.ParseForm() //Parse url parameters passed, then parse the response packet for the POST body (request body)
// attention: If you do not call ParseForm method, the following data can not be obtained form
fmt.Println(r.Form) // print information on server side.
fmt.Println("path", r.URL.Path)
fmt.Println("scheme", r.URL.Scheme)
fmt.Println(r.Form["url_long"])
for k, v := range r.Form {
fmt.Println("key:", k)
fmt.Println("val:", strings.Join(v, ""))
}
fmt.Fprintf(w, "Hello astaxie!") // write data to response
}
func login(w http.ResponseWriter, r *http.Request) {
fmt.Println("method:", r.Method) //get request method
if r.Method == "GET" {
t, _ := template.ParseFiles("login.gtpl")
t.Execute(w, nil)
} else {
r.ParseForm()
// logic part of log in
fmt.Println("username:", r.Form["username"])
fmt.Println("password:", r.Form["password"])
}
}
func main() {
http.HandleFunc("/", sayhelloName) // setting router rule
http.HandleFunc("/login", login)
err := http.ListenAndServe(":9090", nil) // setting listening port
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
Here we use `r.Method` to get the request method, and it returns an http verb -"GET", "POST", "PUT", etc.
In the `login` function, we use `r.Method` to check whether it's a login page or login processing logic. In other words, we check to see whether the user is simply opening the page, or trying to log in. Serve shows the page only when the request comes in via the GET method, and it executes the login logic when the request uses the POST method.
You should see the following interface after opening `http://127.0.0.1:9090/login` in your browser.
![](images/4.1.login.png?raw=true)
Figure 4.1 User login interface
The server will not print anything until after we type in a username and password, because the handler doesn't parse the form until we call `r.ParseForm()`. Let's add `r.ParseForm()` before `fmt.Println("username:", r.Form["username"])`, compile our program and test it again. You will find that the information is printed on the server side now.
`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.
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.
![](images/4.1.slice.png?raw=true)
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.
## Links
- [Directory](preface.md)
- Previous section: [User form](04.0.md)
- Next section: [Verification of inputs](04.2.md)