http编程
一、Http协议
** 1. 什么是协议?**
协议,是指通信的双方,在通信流程或内容格式上,共同遵守的标准。
** 2. 什么是http协议?**
http协议,是互联网中最常见的网络通信标准。
** 3. http协议的特点**
①通信流程:断开式(无状态)
断开式:http协议每次响应完成后,会断开与客户端的连接
无状态:由于服务器断开了之前的连接,就无法知晓连接间的关系
②内容格式:消息头和消息体
二、http编程概述
HTTP(HyperText Transfer Protocol,超文本传输协议)是互联网上应用最为广泛的一种网络协议,定义了客户端和服务端之间请求和响应的传输标准。Go语言标准库内建提供了net/http包,涵盖了HTTP客户端和服务端的具体实现。使用net/http包,我们可以很方便地编写HTTP客户端或服务端的程序。
特点:
-
a. Go原生支持http,import(“net/http”)
-
b. Go的http服务性能和nginx比较接近
-
c. 几行代码就可以实现一个web服务
三、客户端与服务端
-
服务端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 1package main
2
3import (
4 "fmt"
5 "net/http"
6)
7
8//w, 给客户端回复数据
9//r, 读取客户端发送的数据
10func HandConn(w http.ResponseWriter, r *http.Request) {
11 fmt.Println("r.Method = ", r.Method)
12 fmt.Println("r.URL = ", r.URL)
13 fmt.Println("r.Header = ", r.Header)
14 fmt.Println("r.Body = ", r.Body)
15
16 w.Write([]byte("hello go")) //给客户端回复数据
17}
18
19func main() {
20 //注册处理函数,用户连接,自动调用指定的处理函数
21 http.HandleFunc("/", HandConn)
22
23 //监听绑定
24 http.ListenAndServe(":8000", nil)
25}
26
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 1package main
2
3import (
4 "fmt"
5 "net/http"
6)
7
8func Hello(w http.ResponseWriter, r *http.Request) {
9 fmt.Println("r.Method = ", r.Method)
10 fmt.Println("r.URL = ", r.URL)
11 fmt.Println("r.Header = ", r.Header)
12 fmt.Println("r.Body = ", r.Body)
13 fmt.Println("handle hello")
14 fmt.Fprintf(w, "hello ")
15}
16
17func login(w http.ResponseWriter, r *http.Request) {
18 fmt.Println("handle login")
19 fmt.Fprintf(w, "login ")
20}
21
22func history(w http.ResponseWriter, r *http.Request) {
23 fmt.Println("handle history")
24 fmt.Fprintf(w, "history ")
25}
26
27func main() {
28 http.HandleFunc("/", Hello)
29 http.HandleFunc("/user/login", login)
30 http.HandleFunc("/user/history", history)
31 err := http.ListenAndServe("0.0.0.0:8880", nil)
32 if err != nil {
33 fmt.Println("http listen failed")
34 }
35}
36
http_server.go
2. 客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 1package main
2
3import (
4 "fmt"
5 "net/http"
6)
7
8func main() {
9 //resp, err := http.Get("http://www.baidu.com")
10 resp, err := http.Get("http://127.0.0.1:8000")
11 if err != nil {
12 fmt.Println("http.Get err = ", err)
13 return
14 }
15
16 defer resp.Body.Close()
17
18 fmt.Println("Status = ", resp.Status)
19 fmt.Println("StatusCode = ", resp.StatusCode)
20 fmt.Println("Header = ", resp.Header)
21 //fmt.Println("Body = ", resp.Body)
22
23 buf := make([]byte, 4*1024)
24 var tmp string
25
26 for {
27 n, err := resp.Body.Read(buf)
28 if n == 0 {
29 fmt.Println("read err = ", err)
30 break
31 }
32 tmp += string(buf[:n])
33 }
34
35 //读取网页内容,打印出来
36 fmt.Println("tmp = ", tmp)
37}
38
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 1package main
2
3import (
4 "fmt"
5 "io/ioutil"
6 "net/http"
7)
8
9func main() {
10 res, err := http.Get("https://www.baidu.com/")
11 if err != nil {
12 fmt.Println("get err:", err)
13 return
14 }
15
16 data, err := ioutil.ReadAll(res.Body)
17 if err != nil {
18 fmt.Println("get data err:", err)
19 return
20 }
21
22 fmt.Println(string(data))
23}
24
http_client.go
四、http常见请求方法
HTTP请求的方法:
HTTP/1.1协议中共定义了八种方法(有时也叫“动作”),来表明Request-URL指定的资源不同的操作方式
-
1、OPTIONS
1
2 1返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性
2
-
2、HEAD
1
2 1向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。
2
-
3、GET
1
2 1向特定的资源发出请求。它本质就是发送一个请求来取得服务器上的某一资源。资源通过一组HTTP头和呈现数据(如HTML文本,或者图片或者视频等)返回给客户端。GET请求中,永远不会包含呈现数据。
2
-
4、POST
1
2 1向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 Loadrunner中对应POST请求函数:web_submit_data,web_submit_form
2
-
5、PUT
1
2 1向指定资源位置上传其最新内容
2
-
6、DELETE
1
2 1请求服务器删除Request-URL所标识的资源
2
-
7、TRACE
1
2 1回显服务器收到的请求,主要用于测试或诊断
2
-
8、CONNECT
1
2 1HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
2
注意:
- 1)方法名称是区分大小写的,当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Mothod Not Allowed);当服务器不认识或者不支持对应的请求方法时,应返回状态码501(Not Implemented)。
- 2)HTTP服务器至少应该实现GET和HEAD/POST方法,其他方法都是可选的,此外除上述方法,特定的HTTP服务器支持扩展自定义的方法。
1
2
3
4
5
6
7
8
9 1http.StatusContinue = 100
2http.StatusOK = 200
3http.StatusFound = 302
4http.StatusBadRequest = 400
5http.StatusUnauthorized = 401
6http.StatusForbidden = 403
7http.StatusNotFound = 404
8http.StatusInternalServerError = 500
9
常见状态码
get 和 post区别
区别:
get请求无消息体,只能携带少量数据
post请求有消息体,可以携带大量数据
携带数据的方式:
get请求将数据放在url地址中
post请求将数据放在消息体中
GET请求请提交的数据放置在HTTP请求协议头中,而POST提交的数据则放在实体数据中;
GET方式提交的数据最多只能有1024字节,而POST则没有此限制。
五、Head请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 1package main
2
3import (
4 "fmt"
5 "net/http"
6 "net"
7 "time"
8)
9
10var url = []string{
11 "http://www.baidu.com",
12 "http://google.com",
13 "http://taobao.com",
14}
15
16func main() {
17
18 for _, v := range url {
19 c := http.Client{
20 Transport: &http.Transport {
21 Dial:func(network, addr string) (net.Conn, error){
22 timeout := time.Second*2
23 return net.DialTimeout(network, addr, timeout)
24 },
25 },
26 }
27 resp, err := c.Head(v)
28 if err != nil {
29 fmt.Printf("head %s failed, err:%v\n", v, err)
30 continue
31 }
32
33 fmt.Printf("head succ, status:%v\n", resp.Status)
34 }
35}
36
六、表单及panic处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 1package main
2
3import (
4 "io"
5 "log"
6 "net/http"
7)
8
9const form = `<html><body><form action="#" method="post" name="bar">
10 <input type="text" name="in"/>
11 <input type="text" name="in"/>
12 <input type="submit" value="Submit"/>
13 </form></body></html>`
14
15func SimpleServer(w http.ResponseWriter, request *http.Request) {
16 io.WriteString(w, "<h1>hello, world</h1>")
17 panic("test test")
18}
19
20func FormServer(w http.ResponseWriter, request *http.Request) {
21 w.Header().Set("Content-Type", "text/html")
22 switch request.Method {
23 case "GET":
24 io.WriteString(w, form)
25 case "POST":
26 request.ParseForm()
27 io.WriteString(w, request.Form["in"][1])
28 io.WriteString(w, "\n")
29 io.WriteString(w, request.FormValue("in"))
30 }
31}
32func main() {
33 http.HandleFunc("/test1", logPanics(SimpleServer))
34 http.HandleFunc("/test2", logPanics(FormServer))
35 if err := http.ListenAndServe(":8088", nil); err != nil {
36 }
37}
38
39func logPanics(handle http.HandlerFunc) http.HandlerFunc {
40 return func(writer http.ResponseWriter, request *http.Request) {
41 defer func() {
42 if x := recover(); x != nil {
43 log.Printf("[%v] caught panic: %v", request.RemoteAddr, x)
44 }
45 }()
46 handle(writer, request)
47 }
48}
49
七、模板
1. 替换 {{.字段名}}
- if 判断
- if 常见操作
- {{.}}
- {{with .Var}}… {{end}}
2. 循环
{{range.}}… {{end}}
模板示例1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 1package main
2
3import (
4 "fmt"
5 "os"
6 "text/template"
7)
8
9type Person struct {
10 Name string
11 Title string
12 age string
13}
14
15func main() {
16 t, err := template.ParseFiles("day10/template/index.html")
17 if err != nil {
18 fmt.Println("parse file err:", err)
19 return
20 }
21 p := Person{Name: "Mary", age: "31", Title: "我的个人网站"}
22 if err := t.Execute(os.Stdout, p); err != nil {
23 fmt.Println("There was an error:", err.Error())
24 }
25}
26
main.go
1
2
3
4
5
6
7
8
9
10 1<html>
2 <head>
3 <title>{{.Title}}</title>
4 </head>
5 <body>
6 <p> hello, {{.Name}}</p>
7 <p> {{.}}</p>
8 </body>
9 </html>
10
index.html
1
2
3
4
5
6
7
8
9
10 1<html>
2 <head>
3 <title>我的个人网站</title>
4 </head>
5 <body>
6 <p> hello, Mary</p>
7 <p> {Mary 我的个人网站 31}</p>
8 </body>
9</html>
10
1
2 1模板示例2
2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 1package main
2
3import (
4 "fmt"
5 "html/template"
6 "io"
7 "net/http"
8)
9
10var myTemplate *template.Template
11
12type Result struct {
13 output string
14}
15
16func (p *Result) Write(b []byte) (n int, err error) {
17 fmt.Println("called by template")
18 p.output += string(b)
19 return len(b), nil
20}
21
22type Person struct {
23 Name string
24 Title string
25 Age int
26}
27
28func userInfo(w http.ResponseWriter, r *http.Request) {
29 fmt.Println("handle hello")
30 //fmt.Fprintf(w, "hello ")
31 var arr []Person
32 p := Person{Name: "Mary001", Age: 10, Title: "我的个人网站"}
33 p1 := Person{Name: "Mary002", Age: 10, Title: "我的个人网站"}
34 p2 := Person{Name: "Mary003", Age: 10, Title: "我的个人网站"}
35 arr = append(arr, p)
36 arr = append(arr, p1)
37 arr = append(arr, p2)
38
39 resultWriter := &Result{}
40 io.WriteString(resultWriter, "hello world")
41 err := myTemplate.Execute(w, arr)
42 if err != nil {
43 fmt.Println(err)
44 }
45 fmt.Println("template render data:", resultWriter.output)
46 //myTemplate.Execute(w, p)
47 //myTemplate.Execute(os.Stdout, p)
48 //file, err := os.OpenFile("C:/test.log", os.O_CREATE|os.O_WRONLY, 0755)
49 //if err != nil {
50 // fmt.Println("open failed err:", err)
51 // return
52 //}
53
54}
55
56func initTemplate(filename string) (err error) {
57 myTemplate, err = template.ParseFiles(filename)
58 if err != nil {
59 fmt.Println("parse file err:", err)
60 return
61 }
62 return
63}
64
65func main() {
66 initTemplate("day10/template_http/index.html")
67 http.HandleFunc("/user/info", userInfo)
68 err := http.ListenAndServe("0.0.0.0:8880", nil)
69 if err != nil {
70 fmt.Println("http listen failed")
71 }
72}
73
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 1<html>
2 <head>
3 </head>
4 <body>
5 <p>hello world</p>
6 <table border="1">
7 {{range .}}
8 <tr>
9 <td>{{.Name}}</td> <td>{{.Age}}</td><td>{{.Title}}</td>
10 </tr>
11 {{end}}
12 </table>
13 </body>
14</html>
15
index.html
Mysql编程
新建测试表
1
2
3
4
5
6
7
8
9
10
11
12
13 1CREATE TABLE person (
2 user_id int primary key auto_increment,
3 username varchar(260),
4 sex varchar(260),
5 email varchar(260)
6);
7
8CREATE TABLE place (
9 country varchar(200),
10 city varchar(200),
11 telcode int
12)
13
1. 连接mysql
1
2 1database, err := sqlx.Open("mysql", "root:@tcp(127.0.0.1:3306)/test")
2
2. insert操作
1
2 1r, err := Db.Exec("insert into person(username, sex, email)values(?, ?, ?)", "stu001", "man", "stu01@qq.com")
2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 1package main
2
3import (
4 "fmt"
5
6 _ "github.com/go-sql-driver/mysql"
7 "github.com/jmoiron/sqlx"
8)
9
10type Person struct {
11 UserId int `db:"user_id"`
12 Username string `db:"username"`
13 Sex string `db:"sex"`
14 Email string `db:"email"`
15}
16
17type Place struct {
18 Country string `db:"country"`
19 City string `db:"city"`
20 TelCode int `db:"telcode"`
21}
22
23var Db *sqlx.DB
24
25func init() {
26 database, err := sqlx.Open("mysql", "root:0000@tcp(127.0.0.1:3306)/test")
27 if err != nil {
28 fmt.Println("open mysql failed,", err)
29 return
30 }
31 Db = database
32}
33
34func main() {
35 r, err := Db.Exec("insert into person(username, sex, email)values(?, ?, ?)", "stu001", "man", "stu01@qq.com")
36 if err != nil {
37 fmt.Println("exec failed, ", err)
38 return
39 }
40 id, err := r.LastInsertId()
41 if err != nil {
42 fmt.Println("exec failed, ", err)
43 return
44 }
45
46 fmt.Println("insert succ:", id)
47}
48
mysql_insert
3. select操作
1
2 1err := Db.Select(&person, "select user_id, username, sex, email from person where user_id=?", 1)
2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 1package main
2
3import (
4 "fmt"
5
6 _ "github.com/go-sql-driver/mysql"
7 "github.com/jmoiron/sqlx"
8)
9
10type Person struct {
11 UserId int `db:"user_id"`
12 Username string `db:"username"`
13 Sex string `db:"sex"`
14 Email string `db:"email"`
15}
16
17type Place struct {
18 Country string `db:"country"`
19 City string `db:"city"`
20 TelCode int `db:"telcode"`
21}
22
23var Db *sqlx.DB
24
25func init() {
26
27 database, err := sqlx.Open("mysql", "root:0000@tcp(127.0.0.1:3306)/test")
28 if err != nil {
29 fmt.Println("open mysql failed,", err)
30 return
31 }
32
33 Db = database
34}
35
36func main() {
37
38 var person []Person
39 err := Db.Select(&person, "select user_id, username, sex, email from person where user_id=?", 1)
40 if err != nil {
41 fmt.Println("exec failed, ", err)
42 return
43 }
44
45 fmt.Println("select succ:", person)
46}
47
mysql_select
4. update操作
1
2 1_, err := Db.Exec("update person set username=? where user_id=?", "stu0001", 1)
2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 1package main
2
3import (
4 "fmt"
5
6 _ "github.com/go-sql-driver/mysql"
7 "github.com/jmoiron/sqlx"
8)
9
10type Person struct {
11 UserId int `db:"user_id"`
12 Username string `db:"username"`
13 Sex string `db:"sex"`
14 Email string `db:"email"`
15}
16
17type Place struct {
18 Country string `db:"country"`
19 City string `db:"city"`
20 TelCode int `db:"telcode"`
21}
22
23var Db *sqlx.DB
24
25func init() {
26
27 database, err := sqlx.Open("mysql", "root:0000@tcp(127.0.0.1:3306)/test")
28 if err != nil {
29 fmt.Println("open mysql failed,", err)
30 return
31 }
32
33 Db = database
34}
35
36func main() {
37
38 _, err := Db.Exec("update person set username=? where user_id=?", "stu0003", 1)
39 if err != nil {
40 fmt.Println("exec failed, ", err)
41 return
42 }
43
44}
45
mysql_update
5. delete操作
1
2 1_, err := Db.Exec("delete from person where user_id=?", 1)
2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 1package main
2
3import (
4 "fmt"
5
6 _ "github.com/go-sql-driver/mysql"
7 "github.com/jmoiron/sqlx"
8)
9
10type Person struct {
11 UserId int `db:"user_id"`
12 Username string `db:"username"`
13 Sex string `db:"sex"`
14 Email string `db:"email"`
15}
16
17type Place struct {
18 Country string `db:"country"`
19 City string `db:"city"`
20 TelCode int `db:"telcode"`
21}
22
23var Db *sqlx.DB
24
25func init() {
26
27 database, err := sqlx.Open("mysql", "root:0000@tcp(127.0.0.1:3306)/test")
28 if err != nil {
29 fmt.Println("open mysql failed,", err)
30 return
31 }
32
33 Db = database
34}
35
36func main() {
37
38 _, err := Db.Exec("delete from person where user_id=?", 1)
39 if err != nil {
40 fmt.Println("exec failed, ", err)
41 return
42 }
43
44 fmt.Println("delete succ")
45}
46
mysql_delete