在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ GO/ 4.1 處理表單的輸入
7 文本處理
3 Web基礎(chǔ)
14 擴(kuò)展Web框架
10.4 小結(jié)
2.2 Go基礎(chǔ)
2.8 總結(jié)
6.1 session和cookie
5.5 使用beedb庫進(jìn)行ORM開發(fā)
8.3 REST
13.6 小結(jié)
5.4 使用PostgreSQL數(shù)據(jù)庫
14.6 pprof支持
14.1 靜態(tài)文件支持
11.2 使用GDB調(diào)試
7.7 小結(jié)
1 GO環(huán)境配置
14.5 多語言支持
7.1 XML處理
1.5 總結(jié)
13 如何設(shè)計(jì)一個Web框架
14.3 表單及驗(yàn)證支持
12 部署與維護(hù)
10 國際化和本地化
1.1 Go 安裝
6.2 Go如何使用session
5.6 NOSQL數(shù)據(jù)庫操作
6.5 小結(jié)
9.4 避免SQL注入
12.1 應(yīng)用日志
4.2 驗(yàn)證表單的輸入
10.1 設(shè)置默認(rèn)地區(qū)
1.3 Go 命令
9.6 加密和解密數(shù)據(jù)
4.1 處理表單的輸入
4.4 防止多次遞交表單
11.3 Go怎么寫測試用例
8 Web服務(wù)
12.3 應(yīng)用部署
5.7 小結(jié)
12.5 小結(jié)
11 錯誤處理,調(diào)試和測試
9.2 確保輸入過濾
14.2 Session支持
6.4 預(yù)防session劫持
12.4 備份和恢復(fù)
8.1 Socket編程
13.1 項(xiàng)目規(guī)劃
13.4 日志和配置設(shè)計(jì)
7.6 字符串處理
13.2 自定義路由器設(shè)計(jì)
6.3 session存儲
3.4 Go的http包詳解
8.2 WebSocket
10.3 國際化站點(diǎn)
7.5 文件操作
7.4 模板處理
9.1 預(yù)防CSRF攻擊
13.3 controller設(shè)計(jì)
2.6 interface
14.4 用戶認(rèn)證
2.3 流程和函數(shù)
附錄A 參考資料
11.1 錯誤處理
9.5 存儲密碼
9.3 避免XSS攻擊
12.2 網(wǎng)站錯誤處理
6 session和數(shù)據(jù)存儲
2.4 struct類型
3.3 Go如何使得Web工作
2.5 面向?qū)ο?/span>
3.1 Web工作方式
1.2 GOPATH與工作空間
2.1 你好,Go
9.7 小結(jié)
13.5 實(shí)現(xiàn)博客的增刪改
7.2 JSON處理
10.2 本地化資源
7.3 正則處理
2 Go語言基礎(chǔ)
5.1 database/sql接口
4.5 處理文件上傳
8.5 小結(jié)
4.3 預(yù)防跨站腳本
5.3 使用SQLite數(shù)據(jù)庫
14.7 小結(jié)
3.2 Go搭建一個Web服務(wù)器
2.7 并發(fā)
5 訪問數(shù)據(jù)庫
4 表單
3.5 小結(jié)
1.4 Go開發(fā)工具
11.4 小結(jié)
9 安全與加密
5.2 使用MySQL數(shù)據(jù)庫
4.6 小結(jié)
8.4 RPC

4.1 處理表單的輸入

先來看一個表單遞交的例子,我們有如下的表單內(nèi)容,命名成文件login.gtpl(放入當(dāng)前新建項(xiàng)目的目錄里面)

<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>

上面遞交表單到服務(wù)器的/login,當(dāng)用戶輸入信息點(diǎn)擊登陸之后,會跳轉(zhuǎn)到服務(wù)器的路由login里面,我們首先要判斷這個是什么方式傳遞過來,POST還是GET呢?

http包里面有一個很簡單的方式就可以獲取,我們在前面web的例子的基礎(chǔ)上來看看怎么處理login頁面的form數(shù)據(jù)

package main

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

func sayhelloName(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()       //解析url傳遞的參數(shù),對于POST則解析響應(yīng)包的主體(request body)
    //注意:如果沒有調(diào)用ParseForm方法,下面無法獲取表單的數(shù)據(jù)
    fmt.Println(r.Form) //這些信息是輸出到服務(wù)器端的打印信息
    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")
        t.Execute(w, nil)
    } else {
        //請求的是登陸數(shù)據(jù),那么執(zhí)行登陸的邏輯判斷
        fmt.Println("username:", r.Form["username"])
        fmt.Println("password:", r.Form["password"])
    }
}

func main() {
    http.HandleFunc("/", sayhelloName)       //設(shè)置訪問的路由
    http.HandleFunc("/login", login)         //設(shè)置訪問的路由
    err := http.ListenAndServe(":9090", nil) //設(shè)置監(jiān)聽的端口
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

通過上面的代碼我們可以看出獲取請求方法是通過r.Method來完成的,這是個字符串類型的變量,返回GET, POST, PUT等method信息。

login函數(shù)中我們根據(jù)r.Method來判斷是顯示登錄界面還是處理登錄邏輯。當(dāng)GET方式請求時顯示登錄界面,其他方式請求時則處理登錄邏輯,如查詢數(shù)據(jù)庫、驗(yàn)證登錄信息等。

當(dāng)我們在瀏覽器里面打開http://127.0.0.1:9090/login的時候,出現(xiàn)如下界面

http://wiki.jikexueyuan.com/project/go-web-programming/images/4.1.login.png?raw=true" alt="" />

圖4.1 用戶登錄界面

我們輸入用戶名和密碼之后發(fā)現(xiàn)在服務(wù)器端是不會打印出來任何輸出的,為什么呢?默認(rèn)情況下,Handler里面是不會自動解析form的,必須顯式的調(diào)用r.ParseForm()后,你才能對這個表單數(shù)據(jù)進(jìn)行操作。我們修改一下代碼,在fmt.Println("username:", r.Form["username"])之前加一行r.ParseForm(),重新編譯,再次測試輸入遞交,現(xiàn)在是不是在服務(wù)器端有輸出你的輸入的用戶名和密碼了。

r.Form里面包含了所有請求的參數(shù),比如URL中query-string、POST的數(shù)據(jù)、PUT的數(shù)據(jù),所有當(dāng)你在URL的query-string字段和POST沖突時,會保存成一個slice,里面存儲了多個值,Go官方文檔中說在接下來的版本里面將會把POST、GET這些數(shù)據(jù)分離開來。

現(xiàn)在我們修改一下login.gtpl里面form的action值http://127.0.0.1:9090/login修改為http://127.0.0.1:9090/login?username=astaxie,再次測試,服務(wù)器的輸出username是不是一個slice。服務(wù)器端的輸出如下:

http://wiki.jikexueyuan.com/project/go-web-programming/images/4.1.slice.png?raw=true" alt="" />

圖4.2 服務(wù)器端打印接受到的信息

request.Form是一個url.Values類型,里面存儲的是對應(yīng)的類似key=value的信息,下面展示了可以對form數(shù)據(jù)進(jìn)行的一些操作:

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()函數(shù)來獲取用戶提交的參數(shù)。如r.Form["username"]也可寫成r.FormValue("username")。調(diào)用r.FormValue時會自動調(diào)用r.ParseForm,所以不必提前調(diào)用。r.FormValue只會返回同名參數(shù)中的第一個,若參數(shù)不存在則返回空字符串。