go處理form表單輸入
引言
再web開發中(B/S架構),瀏覽器會和服務器進行通信,通信的方式就是表單。
他們之間的基本邏輯為,在服務端寫好HTML文件,當瀏覽器請求界面時,服務器將HTML文件發給瀏覽器,然后用戶在瀏覽器輸入信息,移交之后,將收到的信息一表單發給服務器進行邏輯處理。
get和post
瀏覽器向服務器請求數據一般有兩種方式:get和post。
兩者的異同:
相同點:
都是向服務器發送請求。
不同點:
瀏覽器在向服務器發請求時會攜帶一些信息。get會將請求信息寫在url中,而post會將請求信息寫在請求體body中(get沒有請求體)。
上圖為get的請求方式。
get和post的使用場景:
- get:請求界面,搜索引擎檢索
- post: 提交form表單時。
go處理表單的輸入
源碼:
先來看一個表單遞交的例子,我們有如下的表單內容,命名成文件 login.gtpl(放入當前新建
項目的目錄里面) 。
<html>
<head>
<title></title>
</head>
<body>
<form action="http://127.0.0.1:9090/login" method="post">
用戶名:<input type="text" name="username">
密碼:<input type="password" name="password">
<input type="submit" value="登陸">
</form>
</body>
</html>
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") //解析模板
t.Execute(w, nil) //渲染模板,並發送
} else {
//請求的是登陸數據,那么執行登陸的邏輯判斷
//解析表單
r.ParseForm()
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)
}
}
調試結果:
- 在瀏覽器輸入
127.o.0.1:9090/login
,得到下列界面:
- 輸入數據點擊登陸后,在后台接受的數據為:
細節分析:
當瀏覽器端輸入信息點擊登陸后,輸入的信息會被整理成key-value的形式,並包裝成request包發給服務器,
服務端接收到后的請求r的數據結構是一個結構體,輸入的內容放在了r.Form字段中,這是一個 slice,里面存儲了多 個值。注意在讀取這些值時要先進行解析一下r.ParseForm()
。