1. 什麼是協議?html
協議,是指通訊的雙方,在通訊流程或內容格式上,共同遵照的標準。mysql
2. 什麼是http協議?nginx
http協議,是互聯網中最多見的網絡通訊標準。git
3. http協議的特色github
①通訊流程:斷開式(無狀態)web
斷開式:http協議每次響應完成後,會斷開與客戶端的鏈接sql
無狀態:因爲服務器斷開了以前的鏈接,就沒法知曉鏈接間的關係編程
②內容格式:消息頭和消息體服務器
HTTP(HyperText Transfer Protocol,超文本傳輸協議)是互聯網上應用最爲普遍的一種網絡協議,定義了客戶端和服務端之間請求和響應的傳輸標準。Go語言標準庫內建提供了net/http包,涵蓋了HTTP客戶端和服務端的具體實現。使用net/http包,咱們能夠很方便地編寫HTTP客戶端或服務端的程序。網絡
特色:
a. Go原生支持http,import(「net/http」)
b. Go的http服務性能和nginx比較接近
c. 幾行代碼就能夠實現一個web服務
1. 服務端
package main import ( "fmt" "net/http" ) //w, 給客戶端回覆數據 //r, 讀取客戶端發送的數據 func HandConn(w http.ResponseWriter, r *http.Request) { fmt.Println("r.Method = ", r.Method) fmt.Println("r.URL = ", r.URL) fmt.Println("r.Header = ", r.Header) fmt.Println("r.Body = ", r.Body) w.Write([]byte("hello go")) //給客戶端回覆數據 } func main() { //註冊處理函數,用戶鏈接,自動調用指定的處理函數 http.HandleFunc("/", HandConn) //監聽綁定 http.ListenAndServe(":8000", nil) }
package main import ( "fmt" "net/http" ) func Hello(w http.ResponseWriter, r *http.Request) { fmt.Println("r.Method = ", r.Method) fmt.Println("r.URL = ", r.URL) fmt.Println("r.Header = ", r.Header) fmt.Println("r.Body = ", r.Body) fmt.Println("handle hello") fmt.Fprintf(w, "hello ") } func login(w http.ResponseWriter, r *http.Request) { fmt.Println("handle login") fmt.Fprintf(w, "login ") } func history(w http.ResponseWriter, r *http.Request) { fmt.Println("handle history") fmt.Fprintf(w, "history ") } func main() { http.HandleFunc("/", Hello) http.HandleFunc("/user/login", login) http.HandleFunc("/user/history", history) err := http.ListenAndServe("0.0.0.0:8880", nil) if err != nil { fmt.Println("http listen failed") } }
package main import ( "fmt" "net/http" ) func main() { //resp, err := http.Get("http://www.baidu.com") resp, err := http.Get("http://127.0.0.1:8000") if err != nil { fmt.Println("http.Get err = ", err) return } defer resp.Body.Close() fmt.Println("Status = ", resp.Status) fmt.Println("StatusCode = ", resp.StatusCode) fmt.Println("Header = ", resp.Header) //fmt.Println("Body = ", resp.Body) buf := make([]byte, 4*1024) var tmp string for { n, err := resp.Body.Read(buf) if n == 0 { fmt.Println("read err = ", err) break } tmp += string(buf[:n]) } //讀取網頁內容,打印出來 fmt.Println("tmp = ", tmp) }
package main import ( "fmt" "io/ioutil" "net/http" ) func main() { res, err := http.Get("https://www.baidu.com/") if err != nil { fmt.Println("get err:", err) return } data, err := ioutil.ReadAll(res.Body) if err != nil { fmt.Println("get data err:", err) return } fmt.Println(string(data)) }
返回服務器針對特定資源所支持的HTTP請求方法,也能夠利用向web服務器發送‘*’的請求來測試服務器的功能性
向服務器索與GET請求相一致的響應,只不過響應體將不會被返回。這一方法能夠再沒必要傳輸整個響應內容的狀況下,就能夠獲取包含在響應小消息頭中的元信息。
向特定的資源發出請求。它本質就是發送一個請求來取得服務器上的某一資源。資源經過一組HTTP頭和呈現數據(如HTML文本,或者圖片或者視頻等)返回給客戶端。GET請求中,永遠不會包含呈現數據。
向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會致使新的資源的創建和/或已有資源的修改。 Loadrunner中對應POST請求函數:web_submit_data,web_submit_form
向指定資源位置上傳其最新內容
請求服務器刪除Request-URL所標識的資源
回顯服務器收到的請求,主要用於測試或診斷
HTTP/1.1協議中預留給可以將鏈接改成管道方式的代理服務器。
http.StatusContinue = 100 http.StatusOK = 200 http.StatusFound = 302 http.StatusBadRequest = 400 http.StatusUnauthorized = 401 http.StatusForbidden = 403 http.StatusNotFound = 404 http.StatusInternalServerError = 500
get 和 post區別
區別:
get請求無消息體,只能攜帶少許數據
post請求有消息體,能夠攜帶大量數據
攜帶數據的方式:
get請求將數據放在url地址中
post請求將數據放在消息體中
GET請求請提交的數據放置在HTTP請求協議頭中,而POST提交的數據則放在實體數據中;
GET方式提交的數據最多隻能有1024字節,而POST則沒有此限制。
package main import ( "fmt" "net/http" "net" "time" ) var url = []string{ "http://www.baidu.com", "http://google.com", "http://taobao.com", } func main() { for _, v := range url { c := http.Client{ Transport: &http.Transport { Dial:func(network, addr string) (net.Conn, error){ timeout := time.Second*2 return net.DialTimeout(network, addr, timeout) }, }, } resp, err := c.Head(v) if err != nil { fmt.Printf("head %s failed, err:%v\n", v, err) continue } fmt.Printf("head succ, status:%v\n", resp.Status) } }
package main import ( "io" "log" "net/http" ) const form = `<html><body><form action="#" method="post" name="bar"> <input type="text" name="in"/> <input type="text" name="in"/> <input type="submit" value="Submit"/> </form></body></html>` func SimpleServer(w http.ResponseWriter, request *http.Request) { io.WriteString(w, "<h1>hello, world</h1>") panic("test test") } func FormServer(w http.ResponseWriter, request *http.Request) { w.Header().Set("Content-Type", "text/html") switch request.Method { case "GET": io.WriteString(w, form) case "POST": request.ParseForm() io.WriteString(w, request.Form["in"][1]) io.WriteString(w, "\n") io.WriteString(w, request.FormValue("in")) } } func main() { http.HandleFunc("/test1", logPanics(SimpleServer)) http.HandleFunc("/test2", logPanics(FormServer)) if err := http.ListenAndServe(":8088", nil); err != nil { } } func logPanics(handle http.HandlerFunc) http.HandlerFunc { return func(writer http.ResponseWriter, request *http.Request) { defer func() { if x := recover(); x != nil { log.Printf("[%v] caught panic: %v", request.RemoteAddr, x) } }() handle(writer, request) } }
{{range.}}... {{end}}
模板示例1:
package main import ( "fmt" "os" "text/template" ) type Person struct { Name string Title string age string } func main() { t, err := template.ParseFiles("day10/template/index.html") if err != nil { fmt.Println("parse file err:", err) return } p := Person{Name: "Mary", age: "31", Title: "個人我的網站"} if err := t.Execute(os.Stdout, p); err != nil { fmt.Println("There was an error:", err.Error()) } }
<html> <head> <title>{{.Title}}</title> </head> <body> <p> hello, {{.Name}}</p> <p> {{.}}</p> </body> </html>
<html> <head> <title>個人我的網站</title> </head> <body> <p> hello, Mary</p> <p> {Mary 個人我的網站 31}</p> </body> </html>
模板示例2
package main import ( "fmt" "html/template" "io" "net/http" ) var myTemplate *template.Template type Result struct { output string } func (p *Result) Write(b []byte) (n int, err error) { fmt.Println("called by template") p.output += string(b) return len(b), nil } type Person struct { Name string Title string Age int } func userInfo(w http.ResponseWriter, r *http.Request) { fmt.Println("handle hello") //fmt.Fprintf(w, "hello ") var arr []Person p := Person{Name: "Mary001", Age: 10, Title: "個人我的網站"} p1 := Person{Name: "Mary002", Age: 10, Title: "個人我的網站"} p2 := Person{Name: "Mary003", Age: 10, Title: "個人我的網站"} arr = append(arr, p) arr = append(arr, p1) arr = append(arr, p2) resultWriter := &Result{} io.WriteString(resultWriter, "hello world") err := myTemplate.Execute(w, arr) if err != nil { fmt.Println(err) } fmt.Println("template render data:", resultWriter.output) //myTemplate.Execute(w, p) //myTemplate.Execute(os.Stdout, p) //file, err := os.OpenFile("C:/test.log", os.O_CREATE|os.O_WRONLY, 0755) //if err != nil { // fmt.Println("open failed err:", err) // return //} } func initTemplate(filename string) (err error) { myTemplate, err = template.ParseFiles(filename) if err != nil { fmt.Println("parse file err:", err) return } return } func main() { initTemplate("day10/template_http/index.html") http.HandleFunc("/user/info", userInfo) err := http.ListenAndServe("0.0.0.0:8880", nil) if err != nil { fmt.Println("http listen failed") } }
<html> <head> </head> <body> <p>hello world</p> <table border="1"> {{range .}} <tr> <td>{{.Name}}</td> <td>{{.Age}}</td><td>{{.Title}}</td> </tr> {{end}} </table> </body> </html>
CREATE TABLE person ( user_id int primary key auto_increment, username varchar(260), sex varchar(260), email varchar(260) ); CREATE TABLE place ( country varchar(200), city varchar(200), telcode int )
database, err := sqlx.Open("mysql", "root:@tcp(127.0.0.1:3306)/test")
r, err := Db.Exec("insert into person(username, sex, email)values(?, ?, ?)", "stu001", "man", "stu01@qq.com")
package main import ( "fmt" _ "github.com/go-sql-driver/mysql" "github.com/jmoiron/sqlx" ) type Person struct { UserId int `db:"user_id"` Username string `db:"username"` Sex string `db:"sex"` Email string `db:"email"` } type Place struct { Country string `db:"country"` City string `db:"city"` TelCode int `db:"telcode"` } var Db *sqlx.DB func init() { database, err := sqlx.Open("mysql", "root:0000@tcp(127.0.0.1:3306)/test") if err != nil { fmt.Println("open mysql failed,", err) return } Db = database } func main() { r, err := Db.Exec("insert into person(username, sex, email)values(?, ?, ?)", "stu001", "man", "stu01@qq.com") if err != nil { fmt.Println("exec failed, ", err) return } id, err := r.LastInsertId() if err != nil { fmt.Println("exec failed, ", err) return } fmt.Println("insert succ:", id) }
err := Db.Select(&person, "select user_id, username, sex, email from person where user_id=?", 1)
package main import ( "fmt" _ "github.com/go-sql-driver/mysql" "github.com/jmoiron/sqlx" ) type Person struct { UserId int `db:"user_id"` Username string `db:"username"` Sex string `db:"sex"` Email string `db:"email"` } type Place struct { Country string `db:"country"` City string `db:"city"` TelCode int `db:"telcode"` } var Db *sqlx.DB func init() { database, err := sqlx.Open("mysql", "root:0000@tcp(127.0.0.1:3306)/test") if err != nil { fmt.Println("open mysql failed,", err) return } Db = database } func main() { var person []Person err := Db.Select(&person, "select user_id, username, sex, email from person where user_id=?", 1) if err != nil { fmt.Println("exec failed, ", err) return } fmt.Println("select succ:", person) }
_, err := Db.Exec("update person set username=? where user_id=?", "stu0001", 1)
package main import ( "fmt" _ "github.com/go-sql-driver/mysql" "github.com/jmoiron/sqlx" ) type Person struct { UserId int `db:"user_id"` Username string `db:"username"` Sex string `db:"sex"` Email string `db:"email"` } type Place struct { Country string `db:"country"` City string `db:"city"` TelCode int `db:"telcode"` } var Db *sqlx.DB func init() { database, err := sqlx.Open("mysql", "root:0000@tcp(127.0.0.1:3306)/test") if err != nil { fmt.Println("open mysql failed,", err) return } Db = database } func main() { _, err := Db.Exec("update person set username=? where user_id=?", "stu0003", 1) if err != nil { fmt.Println("exec failed, ", err) return } }
_, err := Db.Exec("delete from person where user_id=?", 1)
package main import ( "fmt" _ "github.com/go-sql-driver/mysql" "github.com/jmoiron/sqlx" ) type Person struct { UserId int `db:"user_id"` Username string `db:"username"` Sex string `db:"sex"` Email string `db:"email"` } type Place struct { Country string `db:"country"` City string `db:"city"` TelCode int `db:"telcode"` } var Db *sqlx.DB func init() { database, err := sqlx.Open("mysql", "root:0000@tcp(127.0.0.1:3306)/test") if err != nil { fmt.Println("open mysql failed,", err) return } Db = database } func main() { _, err := Db.Exec("delete from person where user_id=?", 1) if err != nil { fmt.Println("exec failed, ", err) return } fmt.Println("delete succ") }